home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 23 / AMIGAplus Sonderheft 23 (2000)(Falke)(DE)[!].iso / Updates / AddOns / WormWars / Source / system.c < prev    next >
C/C++ Source or Header  |  1999-11-08  |  85KB  |  2,722 lines

  1. /* $Filename:        WormWars/Source/system.c $
  2.  * $VER:            Worm Wars 4.1 (1.6.99) $
  3.  * $Description:    Amiga-specific code for Worm Wars 4.1 for Amiga $
  4.  *
  5.  * © Copyright 1999 James R. Jacobs.
  6.  * Freely distributable.
  7.  *
  8.  * Prerelease version.
  9.  *        _
  10.  *       //        -=AMIGA=-
  11.  *      //
  12.  * _   //
  13.  * \\ //
  14.  *  \X/
  15.  
  16. #INCLUDES -------------------------------------------------------------- */
  17.  
  18. #include "system.h"                // #includes everything else
  19.  
  20. // GLOBAL VARIABLES (owned by engine.c, imported by amiga.lib) ------------
  21.  
  22. AGLOBAL    struct Library*            TimerBase                        = NULL;
  23.  
  24. // EXTERNAL VARIABLES (owned by engine.c, imported by system.c) -----------
  25.  
  26. IMPORT    struct Library*            SysBase;
  27.  
  28. IMPORT    ABOOL                    clearthem, modified;
  29. IMPORT    SBYTE                    a, board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  30.                                 brush, eachworm[4][2][9],
  31.                                 field[FIELDX + 1][FIELDY + 1],
  32.                                 hi, level, levels, lo,
  33.                                 startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
  34. IMPORT    STRPTR                    pathname;
  35. IMPORT    SWORD                    secondsleft, secondsperlevel;
  36. IMPORT    ULONG                    delay, r;
  37. IMPORT    struct HiScoreStruct    hiscore[HISCORES + 1];
  38. IMPORT    struct OrbStruct        orb[ORBS + 1];
  39. IMPORT    struct TeleportStruct    teleport[MAXLEVELS + 1][4];
  40. IMPORT    struct WormStruct        worm[4];
  41.  
  42. // MODULE VARIABLES (used only within system.c) ---------------------------
  43.  
  44. MODULE    struct ASLBase*            ASLBase                            = NULL;
  45. MODULE    struct GadToolsBase*    GadToolsBase                    = NULL;
  46. MODULE    struct GfxBase*            GfxBase                            = NULL;
  47. MODULE    struct IntuitionBase*    IntuitionBase                    = NULL;
  48. MODULE    struct MEDPlayerBase*    MEDPlayerBase                    = NULL;
  49.  
  50. MODULE    struct FileRequester*    ASLRqPtr                        = NULL;
  51. MODULE    ABOOL                    AudioClosed                        = TRUE;
  52. MODULE    struct MsgPort*            AudioPortPtr[4]                    = {NULL, NULL, NULL, NULL};
  53. MODULE    struct IOAudio*            AudioRqPtr[4]                    = {NULL, NULL, NULL, NULL};
  54. MODULE    SBYTE                    Controller                        = GPCT_NOCONTROLLER;
  55. MODULE    struct timeval*            CurrentValPtr                    = NULL;
  56. MODULE    struct Gadget*            CycleGadgetPtr[4]                = {NULL, NULL, NULL, NULL};
  57. MODULE    ABOOL                    eversent[4];
  58. MODULE    UBYTE*                    fbase                            = NULL;
  59. MODULE    ULONG                    fsize;
  60. MODULE    struct FileHandle*        FilePtr                            = NULL;
  61. MODULE    ABOOL                    fxable                            = FALSE;
  62. MODULE    struct InputEvent        GameEvent;
  63. MODULE    struct Gadget*            GListPtr                        = NULL;
  64. MODULE    ABOOL                    ignore                            = FALSE;
  65. MODULE    ABOOL                    ignorenextjoy;
  66. MODULE    SBYTE                    InputClosed                        = TRUE;
  67. MODULE    struct MsgPort*          InputPortPtr                    = NULL;
  68. MODULE    struct IOStdReq*        InputRqPtr                        = NULL;
  69. MODULE    ABOOL                    joy                                = FALSE;
  70. MODULE    SBYTE                    JoyClosed                        = TRUE;
  71. MODULE    struct MsgPort*            JoyPortPtr                        = NULL;
  72. MODULE    struct IOStdReq*        JoyRqPtr                        = NULL;
  73. MODULE    ULONG                    length[SAMPLES + 1][2];
  74. MODULE    struct Window*            MainWindowPtr                    = NULL;
  75. MODULE    ABOOL                    menu                            = FALSE;
  76. MODULE    struct Menu*            MenuPtr                            = NULL;
  77. MODULE    SBYTE                    mode                            = FALSE;
  78. MODULE    ABOOL                    musicable                        = FALSE;
  79. MODULE    SBYTE                    OldPri                            = 0;
  80. MODULE    APTR                    OldWindowPtr                    = NULL;
  81. MODULE    struct timeval*            PausedValPtr                    = NULL;
  82. MODULE    struct Gadget*            PrevGadgetPtr                    = NULL;
  83. MODULE    struct Process*            ProcessPtr                        = NULL;
  84. MODULE    ULONG                    receipter[4]                    = {(ULONG) -1, (ULONG) -1, (ULONG) -1, (ULONG) -1};
  85. MODULE    UBYTE*                    sbase[SAMPLES + 1];
  86. MODULE    struct Screen*            ScreenPtr                        = NULL;
  87. MODULE    struct MMD0*            SongPtr                            = NULL;
  88. MODULE    ULONG                    speed[SAMPLES + 1];
  89. MODULE    ULONG                    ssize[SAMPLES + 1];
  90. MODULE    struct timeval*            StartValPtr                        = NULL;
  91. MODULE    ABOOL                    sticky                            = FALSE;
  92. MODULE    struct Gadget*            StringGadgetPtr[6]                = {NULL, NULL, NULL, NULL, NULL};
  93. MODULE    SBYTE                    TimerClosed                        = TRUE;
  94. MODULE    struct MsgPort*            TimerPortPtr                    = NULL;
  95. MODULE    struct timerequest*        TimerRqPtr                        = NULL;
  96. MODULE    struct VisualInfo*        VisualInfoPtr                    = NULL;
  97. MODULE    ULONG                    yes[SAMPLES + 1];
  98. MODULE    struct TextAttr            Topaz8 =
  99. {    (STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
  100. };
  101.  
  102. // FUNCTIONS --------------------------------------------------------------
  103.  
  104. int main(int argc, char** argv)
  105. {
  106. ABOOL                argument = FALSE, success = FALSE;
  107. SBYTE                counter, i, player, which;
  108. TEXT                errormessage[SAYLIMIT + 1];
  109. LONG                NewPri;
  110. UWORD                Pens[10] = {BLACK, WHITE, WHITE, WHITE, DARKGREY, PURPLE, BLACK, BLACK, BLUE, (UWORD) ~0};
  111. struct ColorSpec    Colours[21] =
  112. {   /* colour   red     green   blue    description */
  113.     {   0,      0x0,    0x0,    0x0},   //        BLACK
  114.     {   1,      0xF,    0xF,    0xF},   //        WHITE
  115.     {   2,      0x2,    0x2,    0x2},   //    DARKGREY
  116.     {   3,      0x6,    0x6,    0x6},   // medium grey
  117.     {   4,      0xA,    0xA,    0xA},   //   LIGHTGREY
  118.     {   5,      0xE,    0x8,    0x3},   //        ORANGE
  119.     {   6,      0xA,    0x2,    0xA},   //        PURPLE
  120.     {   7,      0x8,    0x4,    0x2},   //        brown
  121.     {   8,      0x3,    0x9,    0x3},   //    DARKGREEN
  122.     {   9,      0x4,    0xE,    0x4},   //  light GREEN
  123.     {   10,     0xF,    0x1,    0x1},   //    DARKRED
  124.     {   11,     0xF,    0x4,    0x4},   //  light RED
  125.     {   12,     0x3,    0x3,    0xF},   //    DARKBLUE
  126.     {   13,     0x6,    0x6,    0xF},   //  light BLUE
  127.     {   14,     0xA,    0x8,    0x3},   //    DARKYELLOW
  128.     {   15,     0xC,    0xC,    0x2},   //  light YELLOW
  129.     {   16,     0x0,    0x0,    0x0},   // pointer: transparent
  130.     {   17,     0xE,    0x4,    0x4},   // pointer: fill
  131.     {   18,     0x3,    0x3,    0x3},   // pointer: shadow
  132.     {   19,     0xC,    0xC,    0xC},   // pointer: shine
  133.     {   -1,     NULL,   NULL,   NULL
  134. }   };
  135. UBYTE*          p8data;
  136. SBYTE            code = 0;
  137. SBYTE            iobuffer[8];        // buffer for 8SVX.VHDR 
  138. SBYTE*           psample[2];         // sample pointers
  139. struct Chunk*   p8Chunk;            // pointers for 8SVX parsing
  140. Voice8Header*   pVoice8Header;
  141. ULONG           rd8count;
  142.  
  143. /* Start of program.
  144.  
  145. version embedding into executable */
  146.  
  147. if (0)    // that is, never
  148.     say(VERSION, ANYTHING);
  149.  
  150. ProcessPtr = (struct Process *) FindTask(NULL);
  151.  
  152. // argument parsing
  153.  
  154. if (argc == 2 && argv[1][0] == '?' && argv[1][1] == '\0')
  155. {   printf("Usage: %s [-p<priority>] [<fieldset>]\n", argv[0]);
  156.     cleanexit(EXIT_SUCCESS);
  157. }
  158. if (argc >= 2)
  159.     for (i = 1; i <= argc - 1; i++)
  160.         if (argv[i][0] == '-' && (argv[i][1] == 'p' || argv[i][1] == 'P'))
  161.         {   stcd_l(&argv[i][2], &NewPri);
  162.             if (NewPri >= -5 && NewPri <= 5)
  163.                   OldPri = SetTaskPri((struct Task *) ProcessPtr, NewPri);
  164.             else
  165.             {   printf("Worm Wars: Priority range is -5 to +5\n", argv[0]);
  166.                 cleanexit(EXIT_FAILURE);
  167.         }   }
  168.         else
  169.         {    argument = TRUE;
  170.             pathname = argv[i];
  171.         }
  172.  
  173. enginesetup();
  174.  
  175. if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37L)))
  176. {    printf("Worm Wars: You need Kickstart R2.04+!\n(Can't open intuition.library V37+!)\n");
  177.     cleanexit(EXIT_FAILURE);
  178. }
  179. if (SysBase->lib_Version < 36L)
  180. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Need exec.library V36+!\0", 24);
  181.     cleanexit(EXIT_FAILURE);
  182. }
  183. if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
  184. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open graphics.library!\0", 24);
  185.     cleanexit(EXIT_FAILURE);
  186. }
  187. if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 37L)))
  188. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open GadTools.library V37+!\0", 24);
  189.     cleanexit(EXIT_FAILURE);
  190. }
  191. if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 0L)))
  192. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open ASL.library!\0", 24);
  193.     cleanexit(EXIT_FAILURE);
  194. }
  195.     
  196. if (!(InputPortPtr = (struct MsgPort *) CreateMsgPort()))
  197. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open input.device!\0", 24);
  198.     cleanexit(EXIT_FAILURE);
  199. }
  200. if (!(InputRqPtr = (struct IOStdReq *) CreateIORequest(InputPortPtr, sizeof(struct IOStdReq))))
  201. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create input I/O request!\0", 24);
  202.     cleanexit(EXIT_FAILURE);
  203. }
  204. if (InputClosed = OpenDevice("input.device", 0, InputRqPtr, 0))
  205. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open input.device!\0", 24);
  206.     cleanexit(EXIT_FAILURE);
  207. }
  208.     
  209. if (!(StartValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  210. {    DisplayAlert(AT_Recovery, ALERTTIMERVALUE, 24);
  211.     cleanexit(EXIT_FAILURE);
  212. }
  213. if (!(CurrentValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  214. {    DisplayAlert(AT_Recovery, ALERTTIMERVALUE, 24);
  215.     cleanexit(EXIT_FAILURE);
  216. }
  217. if (!(PausedValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  218. {    DisplayAlert(AT_Recovery, ALERTTIMERVALUE, 24);
  219.     cleanexit(EXIT_FAILURE);
  220. }
  221. if (!(TimerPortPtr = (struct MsgPort *) CreateMsgPort()))
  222. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer message port!\0", 24);
  223.     cleanexit(EXIT_FAILURE);
  224. }
  225. if (!(TimerRqPtr = (struct timerequest *) CreateIORequest(TimerPortPtr, sizeof(struct timerequest))))
  226. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create timer I/O request!\0", 24);
  227.     cleanexit(EXIT_FAILURE);
  228. }
  229. if (TimerClosed = OpenDevice(TIMERNAME, UNIT_VBLANK, TimerRqPtr, 0))
  230. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open timer.device!\0", 24);
  231.     cleanexit(EXIT_FAILURE);
  232. }
  233. TimerBase = (struct Library *) TimerRqPtr->tr_node.io_Device;
  234.  
  235. /* PREPARE DISPLAY -----------------------------------------------
  236.  
  237. screen */
  238.  
  239. if (!(ScreenPtr = (struct Screen *) OpenScreenTags(NULL,
  240.     SA_Width,            640,
  241.     SA_Height,            256,
  242.     SA_Depth,            4,
  243.     SA_DisplayID,        HIRES_KEY | PAL_MONITOR_ID,
  244.     SA_Title,            TITLEBAR,
  245.     SA_Colors,            Colours,
  246.     SA_Font,            &Topaz8,
  247.     SA_Pens,            Pens,
  248.     TAG_DONE)))
  249.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen!\0", 24);
  250.         cleanexit(EXIT_FAILURE);
  251.     }
  252.  
  253. // GadTools
  254.  
  255. if (!(CycleGadget.ng_VisualInfo = StringGadget.ng_VisualInfo = VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)))
  256. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't get GadTools visual info!\0", 24);
  257.     cleanexit(EXIT_FAILURE);
  258. }
  259. if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
  260. {    DisplayAlert(AT_Recovery, ALERTMENUCREATE, 24);
  261.     cleanexit(EXIT_FAILURE);
  262. }
  263. if (!(LayoutMenus(MenuPtr, VisualInfoPtr, TAG_DONE)))
  264. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't lay out menus!\0", 24);
  265.     cleanexit(EXIT_FAILURE);
  266. }
  267. if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
  268. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools context!\0", 24);
  269.     cleanexit(EXIT_FAILURE);
  270. }
  271. for (player = 0; player <= 3; player++)
  272. {    CycleGadget.ng_TopEdge = 184 + (player * (FONTX + 8));
  273.     CycleGadget.ng_GadgetText = GadgetText[player];
  274.     CycleGadgetPtr[player] = PrevGadgetPtr = (struct Gadget *) CreateGadget(CYCLE_KIND, PrevGadgetPtr, &CycleGadget, GTCY_Labels, GadgetOptions[player], GT_Underscore, '_', GTCY_Active, worm[player].control, TAG_DONE);
  275. }
  276. if (!PrevGadgetPtr)
  277. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create cycle gadgets!\0", 24);
  278.     cleanexit(EXIT_FAILURE);
  279. }
  280.  
  281. // main window
  282.  
  283. if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
  284.     WA_Top,                11,
  285.     WA_Width,            SCREENXPIXEL,
  286.     WA_Height,            SCREENYPIXEL,
  287.     WA_IDCMP,           IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS,
  288.     WA_Gadgets,            GListPtr,
  289.     WA_CustomScreen,    ScreenPtr,
  290.     WA_Borderless,        TRUE,
  291.     WA_Activate,        TRUE,
  292.     WA_SmartRefresh,    TRUE,
  293.     WA_RptQueue,        16,
  294.     TAG_DONE)))
  295.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open main window!\0", 24);
  296.         cleanexit(EXIT_FAILURE);
  297.     }
  298.  
  299. // redirection of AmigaDOS system requesters
  300.     
  301. OldWindowPtr = ProcessPtr->pr_WindowPtr;
  302. ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
  303.  
  304. if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, PATTERN, ASL_Window, MainWindowPtr, TAG_DONE)))
  305. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL request!\0", 24);
  306.     cleanexit(EXIT_FAILURE);
  307. }
  308.  
  309. /* String gadgets: first the window is opened with the cycle gadgets.
  310. It is necessary not to display the string gadgets yet, so the
  311. gadgets are then created and added to the gadget list. You will note
  312. there is no command given to render them as yet. When the attributes
  313. are modified at highscore time, the applicable gadget is refreshed
  314. then. */
  315.  
  316. for (which = 0; which <= HISCORES; which++)
  317. {    StringGadget.ng_TopEdge = 104 + (which * HISCOREDISTANCE);
  318.     StringGadgetPtr[which] = PrevGadgetPtr = (struct Gadget *) CreateGadget(STRING_KIND, PrevGadgetPtr, &StringGadget, GTST_MaxChars, NAMELENGTH, STRINGA_ReplaceMode, TRUE, GA_Disabled, TRUE, TAG_DONE);
  319. }
  320. if (!PrevGadgetPtr)
  321. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create string gadgets!\0", 24);
  322.     cleanexit(EXIT_FAILURE);
  323. }
  324.  
  325. if (!(JoyPortPtr = (struct MsgPort *) CreateMsgPort()))
  326. {    say("Can't create joystick message port!", BLUE);
  327.     anykey(TRUE);
  328. } else if (!(JoyRqPtr = (struct IOStdReq *) CreateIORequest(JoyPortPtr, sizeof(struct IOStdReq))))
  329. {    say("Can't create joystick I/O request!", BLUE);
  330.     anykey(TRUE);
  331. } else if (JoyClosed = OpenDevice("gameport.device", 1, JoyRqPtr, 0))
  332. {    say("Can't open gameport.device!", BLUE);
  333.     anykey(TRUE);
  334. } else
  335. {    Forbid();
  336.     JoyRqPtr->io_Command        = GPD_ASKCTYPE;
  337.     JoyRqPtr->io_Length            = 1;
  338.     JoyRqPtr->io_Flags            = IOF_QUICK;
  339.     JoyRqPtr->io_Data            = (APTR) &Controller;
  340.     DoIO(JoyRqPtr);
  341.     if (Controller == GPCT_NOCONTROLLER)
  342.     {    Controller                = GPCT_ABSJOYSTICK;
  343.         JoyRqPtr->io_Command    = GPD_SETCTYPE;
  344.         JoyRqPtr->io_Length     = 1;
  345.         JoyRqPtr->io_Data        = (APTR) &Controller;
  346.         DoIO(JoyRqPtr);
  347.         success = TRUE;
  348.     }
  349.     Permit();
  350.     if (success)
  351.     {    JoyRqPtr->io_Command    = GPD_SETTRIGGER;
  352.         JoyRqPtr->io_Data        = (APTR) &Trigger;
  353.         JoyRqPtr->io_Length        = sizeof(struct GamePortTrigger);
  354.         DoIO(JoyRqPtr);
  355.         sendreadrequest();
  356.         joy = TRUE;
  357.     } else
  358.     /* Note that say(), anykey() calls must be outside the
  359.     Forbid()/Permit() pair. */
  360.     {    say("Gameport already in use!", BLUE);
  361.         anykey(TRUE);
  362. }    }
  363.  
  364. if (!(MEDPlayerBase = (struct MEDPlayerBase *) OpenLibrary("medplayer.library", 0L)))
  365. {    say("Can't open MEDPlayer.library!", RED);
  366.     anykey(TRUE);
  367. } else
  368. {    say("Loading music...", WHITE);
  369.     if (SongPtr = (struct MMD0 *) LoadModule(MEDMODULE))
  370.         musicable = TRUE;
  371.     else
  372.     {    say("Can't load music!", RED);
  373.         anykey(TRUE);
  374. }    }
  375.  
  376. fxable = TRUE;
  377. for (which = 0; which <= SAMPLES; which++)
  378.     sbase[which] = NULL;
  379. say("Loading sound effects...", WHITE);
  380.  
  381. for (counter = 0; counter <= SAMPLES; counter++)
  382. {   sbase[counter] = (UBYTE *) AllocMem(ssize[counter], MEMF_CHIP | MEMF_CLEAR);
  383.     if (!(FilePtr = (struct FileHandle *) Open(samp[counter].fname, MODE_OLDFILE)))
  384.         code = 1;                               // can't open file
  385.     else
  386.     {   rd8count = Read((BPTR) FilePtr, iobuffer, 8L);
  387.         if (rd8count == -1)
  388.             code = 2;                           // can't read file
  389.         else if (rd8count < 8)
  390.             code = 3;                           // not an IFF 8SVX; too short
  391.         else
  392.         {   p8Chunk = (struct Chunk *) iobuffer;
  393.             if (p8Chunk->ckID != ID_FORM)
  394.                 code = 4;                       // not an IFF FORM
  395.             else if (!(fbase = (UBYTE *) AllocMem(fsize = p8Chunk->ckSize, MEMF_PUBLIC | MEMF_CLEAR)))
  396.                 code = 5;                       // no memory for read
  397.             else
  398.             {   p8data = fbase;
  399.                 rd8count = Read((BPTR) FilePtr, p8data, p8Chunk->ckSize);
  400.                 if (rd8count == -1)
  401.                     code = 6;                   // read error
  402.                 else if (rd8count < p8Chunk->ckSize)
  403.                     code = 7;                   // malformed IFF; too short
  404.                 else if (MAKE_ID(*p8data, *(p8data + 1), *(p8data + 2), *(p8data + 3)) != ID_8SVX)
  405.                     code = 8;                   // not an IFF 8SVX
  406.                 else
  407.                 {   p8data = p8data + 4;
  408.                     while (p8data < fbase + fsize)
  409.                     {   p8Chunk = (struct Chunk *) p8data;
  410.                         switch(p8Chunk->ckID) {
  411.                         case ID_VHDR:
  412.                             pVoice8Header = (Voice8Header *) (p8data + 8L);
  413.                             break;
  414.                         case ID_BODY:
  415.                             psample[0]          = (SBYTE *) (p8data + 8L);
  416.                             psample[1]          = psample[0] + pVoice8Header->oneShotHiSamples;
  417.                             length[counter][0]  = (ULONG) pVoice8Header->oneShotHiSamples;
  418.                             length[counter][1]  = (ULONG) pVoice8Header->repeatHiSamples;
  419. /* To grab the volume level from the IFF 8SVX file, instead
  420. of from the header, add the following line here:
  421. samp[counter].volume  = (SBYTE) (pVoice8Header->volume / 156); */
  422.                             break;
  423.                         default:
  424.                             break;
  425.                         }
  426.                         p8data += 8L + p8Chunk->ckSize;
  427.                         if (p8Chunk->ckSize & 1L == 1)
  428.                             p8data++;
  429.                     }
  430.                     if (length[counter][0] == 0)
  431.                         yes[counter] = 1;
  432.                     else yes[counter] = 0;
  433.                     if (length[counter][yes[counter]] <= 102400)
  434.                         ssize[counter] = length[counter][yes[counter]];
  435.                     else ssize[counter] = 102400;
  436.                     sbase[counter] = (UBYTE *) AllocMem(ssize[counter], MEMF_CHIP | MEMF_CLEAR);
  437.                     if (!sbase[counter])
  438.                         code = 9;               // no chip memory
  439.                     else
  440.                     {   CopyMem(psample[yes[counter]], sbase[counter], ssize[counter]);
  441.                         psample[yes[counter]] += ssize[counter];
  442.                         speed[counter] = PALCLOCK / pVoice8Header->samplesPerSec;
  443.                         if (fbase)
  444.                         {   FreeMem(fbase, fsize);
  445.                             fbase = NULL;
  446.                         }
  447.                         if (FilePtr)
  448.                         {   Close((BPTR) FilePtr);
  449.                             FilePtr = NULL;
  450.     }   }   }   }   }   }
  451.     if (code)
  452.     {   freefx();
  453.         fxable = FALSE;
  454.         strcpy(errormessage, samp[counter].fname);
  455.         strcat(errormessage, ": ");
  456.         strcat(errormessage, sfxerror[code]);
  457.         say(errormessage, RED);
  458.         anykey(TRUE);
  459.         break;
  460. }   }
  461. if (fxable)
  462.     toggle(F);
  463. if (argument && !loadfields(pathname))
  464. {    strcpy(errormessage, "Can't open ");
  465.     strcat(errormessage, pathname);
  466.     strcat(errormessage, "!");
  467.     say(errormessage, RED);
  468.     anykey(TRUE);
  469.     argument = FALSE;
  470.     pathname = DEFAULTSET;
  471. }
  472. if (!argument && !loadfields(DEFAULTSET))
  473. {    strcpy(errormessage, "Can't open ");
  474.     strcat(errormessage, DEFAULTSET);
  475.     strcat(errormessage, "!");
  476.     say(errormessage, RED);
  477.     anykey(TRUE);
  478.     newfields();
  479. }
  480.  
  481. while (1)
  482. {    titlescreen();
  483.  
  484.     // MAIN GAME LOOP -------------------------------------------------
  485.  
  486.     while (a == PLAYGAME)
  487.     {    if (!(++r % VERYSLOW))
  488.         {    GetSysTime(CurrentValPtr);
  489.             SubTime(CurrentValPtr, StartValPtr);
  490.             secondsleft = secondsperlevel - CurrentValPtr->tv_secs;
  491.             timeloop();
  492.         }
  493.         TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  494.         TimerRqPtr->tr_time.tv_secs        = 0;
  495.         TimerRqPtr->tr_time.tv_micro    = delay;
  496.         SendIO(TimerRqPtr);
  497.         gameloop();
  498.         if (CheckIO(TimerRqPtr))
  499.             draw(CLOCKICON, ICONY, CLOCK);
  500.         else
  501.         {    blitmode(BLACK);
  502.             draw(CLOCKICON, ICONY, ANYTHING);
  503.             blitmode(NORMAL);
  504.         }
  505.         WaitIO(TimerRqPtr);
  506.     }
  507.     say("Title Screen", WHITE);
  508. }
  509. }
  510.  
  511. // SUPPORT FUNCTIONS -----------------------------------------------------
  512.  
  513. void activate(SBYTE which)
  514. {    struct InputEvent        InputEvent;
  515.     struct IEPointerPixel    NewPixel;
  516.  
  517.     NewPixel.iepp_Screen        = (struct Screen *) ScreenPtr;
  518.     NewPixel.iepp_Position.X    = 472;
  519.     NewPixel.iepp_Position.Y    = 121 + (which * HISCOREDISTANCE);
  520.     InputEvent.ie_EventAddress    = (APTR) &NewPixel;
  521.     InputEvent.ie_NextEvent        = NULL;
  522.     InputEvent.ie_Class            = IECLASS_NEWPOINTERPOS;
  523.     InputEvent.ie_SubClass        = IESUBCLASS_PIXEL;
  524.     InputEvent.ie_Code            = IECODE_NOBUTTON;
  525.     InputEvent.ie_Qualifier        = NULL;
  526.     InputRqPtr->io_Data            = (APTR) &InputEvent;
  527.     InputRqPtr->io_Length        = sizeof (struct InputEvent);
  528.     InputRqPtr->io_Command        = IND_WRITEEVENT;
  529.     DoIO((struct IORequest *) InputRqPtr);
  530.  
  531.     NewPixel.iepp_Screen        = (struct Screen *) ScreenPtr;
  532.     InputEvent.ie_NextEvent        = NULL;
  533.     InputEvent.ie_Class            = IECLASS_RAWKEY;
  534.     InputEvent.ie_Code            = 0x00;
  535.     InputEvent.ie_Qualifier        = IEQUALIFIER_LCOMMAND + IEQUALIFIER_LALT;
  536.     InputRqPtr->io_Data            = (APTR) &InputEvent;
  537.     InputRqPtr->io_Length        = sizeof (struct InputEvent);
  538.     InputRqPtr->io_Command        = IND_WRITEEVENT;
  539.     DoIO((struct IORequest *) InputRqPtr);
  540.  
  541.     NewPixel.iepp_Screen        = (struct Screen *) ScreenPtr;
  542.     InputEvent.ie_NextEvent        = NULL;
  543.     InputEvent.ie_Class            = IECLASS_RAWMOUSE;
  544.     InputEvent.ie_Code            = 0x00 + IECODE_UP_PREFIX;
  545.     InputEvent.ie_Qualifier        = NULL;
  546.     InputRqPtr->io_Data            = (APTR) &InputEvent;
  547.     InputRqPtr->io_Length        = sizeof (struct InputEvent);
  548.     InputRqPtr->io_Command        = IND_WRITEEVENT;
  549.     DoIO((struct IORequest *) InputRqPtr);
  550. }
  551.  
  552. /* NAME     anykey -- wait for a user press
  553. SYNOPSIS    anykey(ABOOL);
  554. FUNCTION    Waits for a keypress, mousebutton press, or (optionally)
  555.             times out after a few seconds.
  556. INPUTS      timeout - whether to timeout automatically after a few
  557.                       seconds
  558. RESULTS     FALSE if user presses Escape, TRUE otherwise.
  559. FILE        system.c */
  560.  
  561. ABOOL anykey(ABOOL timeout)
  562. {    ABOOL                    done = FALSE;
  563.     SBYTE                    count = 0;
  564.     UWORD                    code, qual;
  565.     ULONG                    class;
  566.     struct IntuiMessage*    MsgPtr;
  567.  
  568.     clearkybd();
  569.     Forbid();
  570.     MainWindowPtr->Flags = WFLG_BORDERLESS | WFLG_ACTIVATE | WFLG_RMBTRAP;
  571.     Permit();
  572.     while (!done)
  573.     {    if (joy && GetMsg(JoyPortPtr))
  574.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  575.                 done = TRUE;
  576.             sendreadrequest();
  577.         }
  578.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  579.         {    class = MsgPtr->Class;
  580.             code  = MsgPtr->Code;
  581.             qual  = MsgPtr->Qualifier;
  582.             GT_ReplyIMsg(MsgPtr);
  583.             if (class == IDCMP_RAWKEY)
  584.             {    if ((!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
  585.                 {    done = TRUE;
  586.                     if (code == M)
  587.                         toggle(M);
  588.                     else if (code == F)
  589.                         toggle(F);
  590.                     else if (code == ESCAPE)
  591.                     {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  592.                         {    if (verify())
  593.                                 cleanexit(EXIT_SUCCESS);
  594.                         } else return(FALSE);
  595.             }   }   }
  596.             else if (class == IDCMP_CLOSEWINDOW)
  597.                 cleanexit(EXIT_SUCCESS);
  598.             else if (class == IDCMP_ACTIVEWINDOW)
  599.                 ignore = TRUE;
  600.             else if (class == IDCMP_MOUSEBUTTONS && !(qual & IEQUALIFIER_REPEAT))
  601.             {    if (ignore)
  602.                 {    if (code == SELECTUP)
  603.                         ignore = FALSE;
  604.                 } else if (code == SELECTDOWN || code == MENUDOWN)
  605.                     done = TRUE;
  606.             } else if (class == IDCMP_INTUITICKS && timeout && ++count > PATIENCE)
  607.                 done = TRUE;
  608.     }    }
  609.     Forbid();
  610.     MainWindowPtr->Flags = WFLG_BORDERLESS | WFLG_ACTIVATE;
  611.     Permit();
  612.     return(TRUE);
  613. }
  614.  
  615. void blitmode(SBYTE state)
  616. {    if (state == BLACK)
  617.     {    Image.PlanePick = 0x0;
  618.         Image.PlaneOnOff = 0x0;
  619.     }
  620.     else if (state == WHITE)
  621.     {    Image.PlanePick = 0x0;
  622.         Image.PlaneOnOff = 0x1;
  623.     }
  624.     else
  625.         Image.PlanePick = 0xf;
  626. }
  627.  
  628. void celebrate(void)
  629. {    ABOOL                    done = FALSE;
  630.     ULONG                    class;
  631.     UWORD                    code, qual;
  632.     struct IntuiMessage*    MsgPtr;
  633.  
  634.     waitasec();
  635.     clearkybd();
  636.     while (done == FALSE)
  637.     {    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  638.         {    class = MsgPtr->Class;
  639.             code  = MsgPtr->Code;
  640.             qual  = MsgPtr->Qualifier;
  641.             GT_ReplyIMsg(MsgPtr);
  642.             switch (class)
  643.             {
  644.             case IDCMP_RAWKEY:
  645.                 if (code == ESCAPE)
  646.                 {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  647.                     {    if (verify())
  648.                             cleanexit(EXIT_SUCCESS);
  649.                     } else
  650.                         done = TRUE;
  651.                 }
  652.                 else if (code == RETURN || code == ENTER || code == SPACEBAR)
  653.                     done = TRUE;
  654.                 else if (code == M)
  655.                     toggle(M);
  656.                 else if (code == F)
  657.                     toggle(F);
  658.                 break;
  659.             case IDCMP_MOUSEBUTTONS:
  660.                 if (!(qual & IEQUALIFIER_REPEAT))
  661.                                 {       if (ignore)
  662.                         {    if (code == SELECTUP)
  663.                                 ignore = FALSE;
  664.                         } else if (code == SELECTDOWN)
  665.                             done = TRUE;
  666.                 } break;
  667.             case IDCMP_ACTIVEWINDOW:
  668.                 ignore = TRUE;
  669.                 break;
  670.             case IDCMP_CLOSEWINDOW:
  671.                 cleanexit(EXIT_SUCCESS);
  672.                 break;
  673.             default:
  674.                 break;
  675.         }    }
  676.         if (joy && GetMsg(JoyPortPtr))
  677.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  678.                 done = TRUE;
  679.             sendreadrequest();
  680.         }
  681.         SetRGB4(&ScreenPtr->ViewPort, 17, rand() % 16, rand() % 16, rand() % 16);
  682.         draw(rand() % (FIELDX + 1), rand() % (FIELDY + 1), rand() % LASTOBJECT);
  683.     }
  684.     SetRGB4(&ScreenPtr->ViewPort, 17, 14, 4, 4);
  685.     a = GAMEOVER;
  686. }
  687.  
  688. void cleanexit(SLONG rc)
  689. {   SBYTE index;
  690.     
  691. if (TimerRqPtr && (!CheckIO(TimerRqPtr)))
  692.                     {    AbortIO(TimerRqPtr);
  693.                         WaitIO(TimerRqPtr);                                }
  694. if (menu)                ClearMenuStrip();
  695. if (mode == FX)     {   freefx();
  696.                         for (index = 0; index <= SAMPLES; index++)
  697.                             if (sbase[index])
  698.                                 FreeMem(sbase[index], ssize[index]);    }
  699. if (mode == MUSIC)        StopPlayer();
  700. if (SongPtr)            UnLoadModule(SongPtr);
  701. if (mode == MUSIC)        FreePlayer();
  702. if (MEDPlayerBase)        CloseLibrary(MEDPlayerBase);
  703. if (joy)            {    AbortIO(JoyRqPtr);
  704.                         WaitIO(JoyRqPtr);                                }
  705. if (Controller != GPCT_NOCONTROLLER)
  706.                     {    Forbid();
  707.                         Controller                = GPCT_NOCONTROLLER;
  708.                         JoyRqPtr->io_Command    = GPD_SETCTYPE;
  709.                         JoyRqPtr->io_Length        = 1;
  710.                         JoyRqPtr->io_Data        = (APTR) &Controller;
  711.                         DoIO(JoyRqPtr);
  712.                         Permit();                                        }
  713. if (!JoyClosed)            CloseDevice(JoyRqPtr);
  714. if (JoyRqPtr)            DeleteIORequest(JoyRqPtr);
  715. if (JoyPortPtr)            DeleteMsgPort(JoyPortPtr);
  716. if (ASLRqPtr)            FreeAslRequest(ASLRqPtr);
  717. if (OldWindowPtr)        ProcessPtr->pr_WindowPtr = OldWindowPtr;
  718. if (MainWindowPtr)    {    clearkybd();
  719.                         CloseWindow(MainWindowPtr);                        }
  720. if (GListPtr)            FreeGadgets(GListPtr);
  721. if (MenuPtr)            FreeMenus(MenuPtr);
  722. if (VisualInfoPtr)        FreeVisualInfo(VisualInfoPtr);
  723. if (ScreenPtr)            CloseScreen(ScreenPtr);
  724. if (!TimerClosed)        CloseDevice(TimerRqPtr);
  725. if (TimerRqPtr)            DeleteIORequest(TimerRqPtr);
  726. if (TimerPortPtr)        DeleteMsgPort(TimerPortPtr);
  727. if (PausedValPtr)        FreeMem(PausedValPtr, sizeof(struct timeval));
  728. if (CurrentValPtr)        FreeMem(CurrentValPtr, sizeof(struct timeval));
  729. if (StartValPtr)        FreeMem(StartValPtr, sizeof(struct timeval));
  730. if (!InputClosed)        CloseDevice(InputRqPtr);
  731. if (InputRqPtr)            DeleteIORequest(InputRqPtr);
  732. if (InputPortPtr)        DeleteMsgPort(InputPortPtr);
  733. if (ASLBase)            CloseLibrary(ASLBase);
  734. if (GadToolsBase)        CloseLibrary(GadToolsBase);
  735. if (GfxBase)            CloseLibrary(GfxBase);
  736. if (IntuitionBase)    {    OpenWorkBench();
  737.                         CloseLibrary(IntuitionBase);                    }
  738.                         SetTaskPri((struct Task *) ProcessPtr, OldPri);
  739.                         exit(rc);                // End of program.
  740. }
  741.  
  742. void clearjoystick(void)
  743. {    if (joy)
  744.         while (GetMsg(JoyPortPtr))
  745.             sendreadrequest();
  746. }
  747.  
  748. void clearkybd(void)
  749. {    struct IntuiMessage* MsgPtr;
  750.     
  751.     while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  752.         GT_ReplyIMsg(MsgPtr);
  753. }
  754.  
  755. void clearstats(void)
  756. {    SetAPen(MainWindowPtr->RPort, BLACK);
  757.     RectFill(MainWindowPtr->RPort, 0, STARTYPIXEL, STARTXPIXEL - 1, ENDYPIXEL);
  758.     RectFill(MainWindowPtr->RPort, ENDXPIXEL + 1, STARTYPIXEL, SCREENXPIXEL, SCREENYPIXEL);
  759.     if (mode == MUSIC)
  760.         draw(MUSICICON, ICONY, MUSIC);
  761.     else if (mode == FX)
  762.         draw(MUSICICON, ICONY, FX);
  763.     if (sticky)
  764.         draw(STICKYICON, ICONY, STICKY);
  765. }
  766.  
  767. void draw(SBYTE x, SBYTE y, SBYTE image)
  768. {    Image.ImageData = ImageData[image];
  769.     DrawImage(MainWindowPtr->RPort, &Image, (x * SQUAREX) + STARTXPIXEL, (y * SQUAREY) + STARTYPIXEL);
  770. }
  771.  
  772. ULONG effect(SBYTE index)
  773. {           SBYTE    i;
  774.             SBYTE    ok                = -1;
  775.             ULONG   oldestreceipt    = (ULONG) -1L;
  776.     PERSIST    ULONG   receipt            = 1L;
  777.  
  778.     /* oldestreceipt = temporary variable for ascertaining oldest
  779.     sound still playing.
  780.     receipt = next unused receipt number (monotonically incrementing). */
  781.  
  782.     if (mode == FX)
  783.     {    for (i = 0; i <= 3; i++)
  784.         {    // decide on a channel
  785.  
  786.             if (ok == -1)
  787.             {    if (!eversent[i])
  788.                     ok = i;
  789.                 else if (CheckIO(AudioRqPtr[i]))
  790.                 {    WaitIO(AudioRqPtr[i]);
  791.                     ok = i;
  792.         }    }    }
  793.         if (ok == -1)
  794.         {   for (i = 0; i <= 3; i++)
  795.                 if (receipter[i] < oldestreceipt)
  796.                 {   ok = i;
  797.                     oldestreceipt = receipter[i];
  798.                 }
  799.             AbortIO(AudioRqPtr[ok]);
  800.             WaitIO(AudioRqPtr[ok]);
  801.         }
  802.         eversent[ok] = TRUE;
  803.         if (samp[index].repeat)
  804.             AudioRqPtr[ok]->ioa_Cycles          = 0;
  805.         else
  806.             AudioRqPtr[ok]->ioa_Cycles          = 1;
  807.         AudioRqPtr[ok]->ioa_Request.io_Command  = CMD_WRITE;
  808.         AudioRqPtr[ok]->ioa_Request.io_Flags    = ADIOF_PERVOL;
  809.         AudioRqPtr[ok]->ioa_Request.io_Unit     = (1 << ok);
  810.         AudioRqPtr[ok]->ioa_Volume              = samp[index].volume;
  811.         AudioRqPtr[ok]->ioa_Period              = (UWORD) speed[index];
  812.         AudioRqPtr[ok]->ioa_Request.io_Message.mn_ReplyPort
  813.                                                 = AudioPortPtr[ok];
  814.         AudioRqPtr[ok]->ioa_Data                = (UBYTE *) sbase[index];
  815.         AudioRqPtr[ok]->ioa_Length              = length[index][yes[index]];
  816.         BeginIO(AudioRqPtr[ok]);
  817.         receipter[ok] = receipt;
  818.         return(receipt++);
  819. }   }
  820.  
  821. void fieldedit(void)
  822. {    UBYTE                    oldbrush = ANYTHING, stamp;
  823.     SBYTE                    deltax = 0, deltay = 0, lastx, lasty, pointerx, pointery, which, x, y;
  824.     UWORD                    code, qual;
  825.     ULONG                    class;
  826.     struct IntuiMessage*    MsgPtr;
  827.     ABOOL                    leftdown = FALSE, rightdown = FALSE, timer = FALSE;
  828.  
  829. ClearMenuStrip(MenuPtr);
  830. menu = FALSE;
  831. NewMenu[TOOLSSTART + 1 + IN_TS].nm_Flags = CHECKIT | MENUTOGGLE;
  832. NewMenu[TOOLSSTART + 1 + IN_FE].nm_Flags = CHECKIT | MENUTOGGLE | CHECKED | NM_ITEMDISABLED;
  833. NewMenu[LEVELSTART].nm_Flags = 0;
  834. if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
  835. {    DisplayAlert(AT_Recovery, ALERTMENUCREATE, 24);
  836.     cleanexit(EXIT_FAILURE);
  837. }
  838. if (!(LayoutMenus(MenuPtr, VisualInfoPtr, TAG_DONE)))
  839. {    DisplayAlert(AT_Recovery, ALERTMENULAYOUT, 24);
  840.     if (modified)
  841.         savefields(EMERGENCYNAME);
  842.     cleanexit(EXIT_FAILURE);
  843. }
  844. SetMenuStrip(MainWindowPtr, MenuPtr);
  845. menu = TRUE;
  846.  
  847. say("Field Editor", WHITE);
  848. setpointer(brush);
  849. if (level > levels)
  850.     level = levels;
  851.  
  852. // draw pseudo-gadgets
  853.  
  854. clearstats();
  855. for (which = 0; which <= 7; which++)
  856.     DrawBevelBox(MainWindowPtr->RPort, STARTXPIXEL - 5 - (SQUAREX * 3), 46 + STARTYPIXEL + (which * SQUAREY * 3), SQUAREX + 9, SQUAREY + 4, GT_VisualInfo, VisualInfoPtr);
  857. SetAPen(MainWindowPtr->RPort, WHITE);
  858. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  GOLDGADGET * SQUAREY));
  859. Text(MainWindowPtr->RPort, "F1:", 3);
  860. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (SILVERGADGET * SQUAREY));
  861. Text(MainWindowPtr->RPort, "F2:", 3);
  862. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( EMPTYGADGET * SQUAREY));
  863. Text(MainWindowPtr->RPort, "F3:", 3);
  864. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  WOODGADGET * SQUAREY));
  865. Text(MainWindowPtr->RPort, "F4:", 3);
  866. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( STONEGADGET * SQUAREY));
  867. Text(MainWindowPtr->RPort, "F5:", 3);
  868. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   ONEGADGET * SQUAREY));
  869. Text(MainWindowPtr->RPort, "F6:", 3);
  870. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   TWOGADGET * SQUAREY));
  871. Text(MainWindowPtr->RPort, "F7:", 3);
  872. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( STARTGADGET * SQUAREY));
  873. Text(MainWindowPtr->RPort, "F8:", 3);
  874. draw(GADGETX,   GOLDGADGET,   GOLD);
  875. draw(GADGETX, SILVERGADGET, SILVER);
  876. draw(GADGETX,  EMPTYGADGET,  EMPTY);
  877. draw(GADGETX,   WOODGADGET,   WOOD);
  878. draw(GADGETX,  STONEGADGET,  STONE);
  879. draw(GADGETX,    ONEGADGET,       ONE);
  880. draw(GADGETX,    TWOGADGET,    TWO);
  881. draw(GADGETX,  STARTGADGET,  START);
  882. underline(brush);
  883.  
  884. renderboard();
  885. saylevel(WHITE);
  886. clearkybd();
  887. x = lastx = startx[level];
  888. y = lasty = starty[level];
  889.     
  890. while (a == FIELDEDIT)
  891. {    stamp = NOSQUARE;
  892.  
  893.     if (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  894.     {    class = MsgPtr->Class;
  895.         code  = MsgPtr->Code;
  896.         qual  = MsgPtr->Qualifier;
  897.         if (class == IDCMP_MENUVERIFY && MsgPtr->MouseX >= STARTXPIXEL && MsgPtr->MouseX <= ENDXPIXEL && MsgPtr->MouseY >= STARTYPIXEL && MsgPtr->MouseY <= ENDYPIXEL)
  898.         {    MsgPtr->Code = MENUCANCEL;
  899.             oldbrush = brush;
  900.             brush = EMPTY;
  901.             rightdown = TRUE;
  902.         }
  903.         ReplyMsg(MsgPtr);
  904.         switch (class)
  905.         {
  906.         case IDCMP_MENUPICK:
  907.             if (code != MENUNULL)
  908.             {    switch (MENUNUM(code))
  909.                 {
  910.                 case MN_PROJECT:
  911.                     switch (ITEMNUM(code))
  912.                     {
  913.                     case IN_NEW:
  914.                         effect(FXFILENEW);
  915.                         newfields();
  916.                         say("New done.", WHITE);
  917.                         break;
  918.                     case IN_OPEN:
  919.                         effect(FXFILEOPEN);
  920.                         fileopen();
  921.                         break;
  922.                     case IN_SAVE:
  923.                         effect(FXFILESAVE);
  924.                         filesaveas(FALSE);
  925.                         break;
  926.                     case IN_SAVEAS:
  927.                         effect(FXFILESAVEAS);
  928.                         filesaveas(TRUE);
  929.                         break;
  930.                     case IN_ABOUT:
  931.                         fileabout();
  932.                         break;
  933.                     case IN_QUIT:
  934.                         if (verify())
  935.                             cleanexit(EXIT_SUCCESS);
  936.                         break;
  937.                     default:
  938.                         break;
  939.                     }
  940.                     break;
  941.                 case MN_TOOLS:
  942.                     a = GAMEOVER;
  943.                     break;
  944.                 case MN_LEVEL:
  945.                     switch (ITEMNUM(code))
  946.                     {
  947.                     case IN_INSERT:
  948.                         levelinsert();
  949.                         break;
  950.                     case IN_DELETE:
  951.                         leveldelete();
  952.                         break;
  953.                     case IN_ERASE:
  954.                         levelerase();
  955.                         break;
  956.                     case IN_APPEND:
  957.                         levelappend();
  958.                         break;
  959.                     default:
  960.                         break;
  961.                     }
  962.                     break;
  963.                 default:
  964.                     break;
  965.             }    }
  966.             break;
  967.         case IDCMP_RAWKEY:
  968.             lastx = x;
  969.             lasty = y;
  970.             switch(code)
  971.             {
  972.             case DELETE:
  973.                 if (!(qual & IEQUALIFIER_REPEAT))
  974.                 {    effect(FXCLICK);
  975.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  976.                         level = 1;
  977.                     else if (--level < 0)
  978.                         level = levels;
  979.                     saylevel(WHITE);
  980.                     renderboard();
  981.                 }
  982.                 break;
  983.             case HELP:
  984.                 if (!(qual & IEQUALIFIER_REPEAT))
  985.                 {    effect(FXCLICK);
  986.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  987.                         level = levels;
  988.                     else if (++level > levels)
  989.                         level = 0;
  990.                     saylevel(WHITE);
  991.                     renderboard();
  992.                 }
  993.                 break;
  994.             case M:
  995.                 if (!(qual & IEQUALIFIER_REPEAT))
  996.                     toggle(M);
  997.                 break;
  998.             case F:
  999.                 if (!(qual & IEQUALIFIER_REPEAT))
  1000.                     toggle(F);
  1001.                 break;
  1002.             case ESCAPE:
  1003.                 if (!(qual & IEQUALIFIER_REPEAT))
  1004.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1005.                     {   if (verify())
  1006.                             cleanexit(EXIT_SUCCESS);
  1007.                     } else a = GAMEOVER;
  1008.                 break;
  1009.             case SPACEBAR:
  1010.             case RETURN:
  1011.             case ENTER:
  1012.                 if (!(qual & IEQUALIFIER_REPEAT))
  1013.                     a = GAMEOVER;
  1014.                 break;
  1015.             case N:
  1016.                 if (!(qual & IEQUALIFIER_REPEAT))
  1017.                 {    effect(FXFILENEW);
  1018.                     newfields();
  1019.                     say("New done.", WHITE);
  1020.                 }
  1021.                 break;
  1022.             case O:
  1023.                 if (!(qual & IEQUALIFIER_REPEAT))
  1024.                 {    effect(FXFILEOPEN);
  1025.                     fileopen();
  1026.                 }
  1027.                 break;
  1028.             case S:
  1029.                 if (!(qual & IEQUALIFIER_REPEAT))
  1030.                 {    effect(FXFILESAVE);
  1031.                     filesaveas(FALSE);
  1032.                 }
  1033.                 break;
  1034.             case A:
  1035.                 if (!(qual & IEQUALIFIER_REPEAT))
  1036.                 {   effect(FXFILESAVEAS);
  1037.                     filesaveas(TRUE);
  1038.                 }
  1039.                 break;
  1040.             case Q:
  1041.                 if (!(qual & IEQUALIFIER_REPEAT))
  1042.                 {   if (verify())
  1043.                         cleanexit(EXIT_SUCCESS);
  1044.                 }
  1045.                 break;
  1046.             case NUMERICOPEN:
  1047.                 effect(FXCLICK);
  1048.                 setpointer(NORMAL);
  1049.                 underline(-1);
  1050.                 if (brush-- == 0 || brush > LASTOBJECT)
  1051.                     brush = LASTOBJECT;
  1052.                 stamp = brush;
  1053.                 break;
  1054.             case NUMERICCLOSE:
  1055.                 effect(FXCLICK);
  1056.                 setpointer(NORMAL);
  1057.                 underline(-1);
  1058.                 if (++brush > LASTOBJECT)
  1059.                     brush = 0;
  1060.                 stamp = brush;
  1061.                 break;
  1062.             case I:
  1063.                 effect(FXCLICK);
  1064.                 if (!(qual & IEQUALIFIER_REPEAT))
  1065.                     levelinsert();
  1066.                 break;
  1067.             case D:
  1068.                 effect(FXCLICK);
  1069.                 if (!(qual & IEQUALIFIER_REPEAT))
  1070.                     leveldelete();
  1071.                 break;
  1072.             case E:
  1073.                 effect(FXCLICK);
  1074.                 if (!(qual & IEQUALIFIER_REPEAT))
  1075.                     levelerase();
  1076.                 break;
  1077.             case K:
  1078.                 effect(FXCLICK);
  1079.                 if (!(qual & IEQUALIFIER_REPEAT))
  1080.                     levelappend();
  1081.                 break;
  1082.             case ALPHAONE:
  1083.                 effect(FXCLICK);
  1084.                 stamp = GOLD;
  1085.                 break;
  1086.             case ALPHATWO:
  1087.                 effect(FXCLICK);
  1088.                 stamp = SILVER;
  1089.                 break;
  1090.             case ALPHATHREE:
  1091.                 effect(FXCLICK);
  1092.                 stamp = EMPTY;
  1093.                 break;
  1094.             case ALPHAFOUR:
  1095.                 effect(FXCLICK);
  1096.                 stamp = WOOD;
  1097.                 break;
  1098.             case ALPHAFIVE:
  1099.                 effect(FXCLICK);
  1100.                 stamp = STONE;
  1101.                 break;
  1102.             case ALPHASIX:
  1103.                 effect(FXCLICK);
  1104.                 stamp = ONE;
  1105.                 break;
  1106.             case ALPHASEVEN:
  1107.                 effect(FXCLICK);
  1108.                 stamp = TWO;
  1109.                 break;
  1110.             case ALPHAEIGHT:
  1111.                 effect(FXCLICK);
  1112.                 stamp = START;
  1113.                 break;
  1114.             case F1:
  1115.                 if (!(qual & IEQUALIFIER_REPEAT))
  1116.                 {    effect(FXCLICK);
  1117.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1118.                         fillfield(GOLD);
  1119.                     else setbrush(GOLD);
  1120.                 }
  1121.                 break;
  1122.             case F2:
  1123.                 if (!(qual & IEQUALIFIER_REPEAT))
  1124.                 {    effect(FXCLICK);
  1125.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1126.                         fillfield(SILVER);
  1127.                     else setbrush(SILVER);
  1128.                 }
  1129.                 break;
  1130.             case F3:
  1131.                 if (!(qual & IEQUALIFIER_REPEAT))
  1132.                 {    effect(FXCLICK);
  1133.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1134.                         fillfield(EMPTY);
  1135.                     else setbrush(EMPTY);
  1136.                 }
  1137.                 break;
  1138.             case F4:
  1139.                 if (!(qual & IEQUALIFIER_REPEAT))
  1140.                 {    effect(FXCLICK);
  1141.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1142.                         fillfield(WOOD);
  1143.                     else setbrush(WOOD);
  1144.                 }
  1145.                 break;
  1146.             case F5:
  1147.                 if (!(qual & IEQUALIFIER_REPEAT))
  1148.                 {    effect(FXCLICK);
  1149.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1150.                         fillfield(STONE);
  1151.                     else setbrush(STONE);
  1152.                 }
  1153.                 break;
  1154.             case F6:
  1155.                 if (!(qual & IEQUALIFIER_REPEAT))
  1156.                 {    effect(FXCLICK);
  1157.                     setbrush(ONE);
  1158.                 }
  1159.                 break;
  1160.             case F7:
  1161.                 if (!(qual & IEQUALIFIER_REPEAT))
  1162.                 {    effect(FXCLICK);
  1163.                     setbrush(TWO);
  1164.                 }
  1165.                 break;
  1166.             case F8:
  1167.                 if (!(qual & IEQUALIFIER_REPEAT))
  1168.                 {    effect(FXCLICK);
  1169.                     setbrush(START);
  1170.                 }
  1171.                 break;
  1172.             case NUMERICZERO:
  1173.                 effect(FXCLICK);
  1174.                 if (!(qual & IEQUALIFIER_REPEAT))
  1175.                 {    if (!sticky)
  1176.                     {    sticky = TRUE;
  1177.                         draw(STICKYICON, ICONY, STICKY);
  1178.                         stamp = brush;
  1179.                     } else
  1180.                     {    sticky = FALSE;
  1181.                         blitmode(BLACK);
  1182.                         draw(STICKYICON, ICONY, ANYTHING);
  1183.                         blitmode(NORMAL);
  1184.                 }    }
  1185.                 break;
  1186.             case NUMERICDOT:
  1187.                 effect(FXCLICK);
  1188.                 if (!(qual & IEQUALIFIER_REPEAT))
  1189.                     stamp = brush;
  1190.                 break;
  1191.             case NUMERICFOUR:
  1192.             case LEFT:
  1193.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1194.                     x = 0;
  1195.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1196.                     x = xwrap(x - ALTJUMP);
  1197.                 else
  1198.                     x = xwrap(x - 1);
  1199.                 if (sticky)
  1200.                     stamp = brush;
  1201.                 break;
  1202.             case NUMERICSIX:
  1203.             case RIGHT:
  1204.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1205.                     x = FIELDX;
  1206.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1207.                     x = xwrap(x + ALTJUMP);
  1208.                 else
  1209.                     x = xwrap(x + 1);
  1210.                 if (sticky)
  1211.                     stamp = brush;
  1212.                 break;
  1213.             case NUMERICEIGHT:
  1214.             case UP:
  1215.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1216.                     y = 0;
  1217.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1218.                     y = ywrap(y - ALTJUMP);
  1219.                 else
  1220.                     y = ywrap(y - 1);
  1221.                 if (sticky)
  1222.                     stamp = brush;
  1223.                 break;
  1224.             case NUMERICFIVE:
  1225.             case NUMERICTWO:
  1226.             case DOWN:
  1227.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1228.                     y = FIELDY;
  1229.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1230.                     y = ywrap(y + ALTJUMP);
  1231.                 else
  1232.                     y = ywrap(y + 1);
  1233.                 if (sticky)
  1234.                     stamp = brush;
  1235.                 break;
  1236.             case NUMERICSEVEN:
  1237.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1238.                 {    x = 0;
  1239.                     y = 0;
  1240.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1241.                 {    x = xwrap(x - ALTJUMP);
  1242.                     y = ywrap(y - ALTJUMP);
  1243.                 } else
  1244.                 {    x = xwrap(x - 1);
  1245.                     y = ywrap(y - 1);
  1246.                 }
  1247.                 if (sticky)
  1248.                     stamp = brush;
  1249.                 break;
  1250.             case NUMERICNINE:
  1251.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1252.                 {    x = FIELDX;
  1253.                     y = 0;
  1254.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1255.                 {    x = xwrap(x + ALTJUMP);
  1256.                     y = ywrap(y - ALTJUMP);
  1257.                 } else
  1258.                 {    x = xwrap(x + 1);
  1259.                     y = ywrap(y - 1);
  1260.                 }
  1261.                 if (sticky)
  1262.                     stamp = brush;
  1263.                 break;
  1264.             case NUMERICONE:
  1265.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1266.                 {    x = 0;
  1267.                     y = FIELDY;
  1268.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1269.                 {    x = xwrap(x - ALTJUMP);
  1270.                     y = ywrap(y + ALTJUMP);
  1271.                 } else
  1272.                 {    x = xwrap(x - 1);
  1273.                     y = ywrap(y + 1);
  1274.                 }
  1275.                 if (sticky)
  1276.                     stamp = brush;
  1277.                 break;
  1278.             case NUMERICTHREE:
  1279.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1280.                 {    x = FIELDX;
  1281.                     y = FIELDY;
  1282.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1283.                 {    x = xwrap(x + ALTJUMP);
  1284.                     y = ywrap(y + ALTJUMP);
  1285.                 } else
  1286.                 {    x = xwrap(x + 1);
  1287.                     y = ywrap(y + 1);
  1288.                 }
  1289.                 if (sticky)
  1290.                     stamp = brush;
  1291.                 break;
  1292.             default:
  1293.                 break;
  1294.             }
  1295.             if (x != lastx || y != lasty)
  1296.             {    updatesquare(lastx, lasty);
  1297.                 if (stamp == NOSQUARE)
  1298.                 {    blitmode(WHITE);
  1299.                     draw(x, y, ANYTHING);
  1300.                     blitmode(NORMAL);
  1301.             }    }
  1302.             break;
  1303.         case IDCMP_MOUSEBUTTONS:
  1304.             updatesquare(x, y);
  1305.             switch (code)
  1306.             {
  1307.             case SELECTUP:
  1308.                 if (ignore)
  1309.                     ignore = FALSE;
  1310.                 else leftdown = FALSE;
  1311.                 break;
  1312.             case SELECTDOWN:
  1313.                 if (!ignore)
  1314.                 {    effect(FXCLICK);
  1315.                     leftdown = TRUE;
  1316.                 }
  1317.                 break;
  1318.             case MENUUP:
  1319.                 rightdown = FALSE;
  1320.                 brush = oldbrush;
  1321.                 oldbrush = ANYTHING;
  1322.                 break;
  1323.             default:
  1324.                 // MENUDOWN
  1325.                 break;
  1326.             }
  1327.             break;
  1328.         case IDCMP_ACTIVEWINDOW:
  1329.             ignore = TRUE;
  1330.             break;
  1331.         case IDCMP_CLOSEWINDOW:
  1332.             cleanexit(EXIT_SUCCESS);
  1333.             break;
  1334.         case IDCMP_REFRESHWINDOW:
  1335.             GT_BeginRefresh(MainWindowPtr);
  1336.             GT_EndRefresh(MainWindowPtr, TRUE);
  1337.             break;
  1338.         default:
  1339.             // IDCMP_MENUVERIFY, IDCMP_INTUITICKS
  1340.             break;
  1341.     }    }
  1342.     else if (joy)
  1343.     {    if (GetMsg(JoyPortPtr))
  1344.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  1345.                 stamp = brush;
  1346.             deltax = (SBYTE) GameEvent.ie_position.ie_xy.ie_x;
  1347.             deltay = (SBYTE) GameEvent.ie_position.ie_xy.ie_y;
  1348.             if (GameEvent.ie_Qualifier == IEQUALIFIER_LEFTBUTTON)
  1349.                 stamp = brush;
  1350.             sendreadrequest();
  1351.         }
  1352.         if (deltax || deltay)
  1353.         {    if (!timer)
  1354.             {    TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  1355.                 TimerRqPtr->tr_time.tv_secs        = 0;
  1356.                 TimerRqPtr->tr_time.tv_micro    = JOYDELAY;
  1357.                 SendIO(TimerRqPtr);
  1358.                 timer = TRUE;
  1359.             } else if (CheckIO(TimerRqPtr))
  1360.             {    lastx = x;
  1361.                 lasty = y;
  1362.                 x = xwrap(x + deltax);
  1363.                 y = ywrap(y + deltay);    
  1364.                 updatesquare(lastx, lasty);
  1365.                 if (stamp == NOSQUARE)
  1366.                 {    blitmode(WHITE);
  1367.                       draw(x, y, ANYTHING);
  1368.                     blitmode(NORMAL);
  1369.                 }
  1370.                 timer = FALSE;
  1371.     }    }    }
  1372.     if (leftdown || rightdown)
  1373.     {    pointerx = xpixeltosquare(MainWindowPtr->MouseX);
  1374.         pointery = ypixeltosquare(MainWindowPtr->MouseY);
  1375.         if (valid(pointerx, pointery))
  1376.         {    x = pointerx;
  1377.             y = pointery;
  1378.             stamp = brush;
  1379.             updatesquare(lastx, lasty);
  1380.         }
  1381.         else if (leftdown && pointerx == GADGETX &&
  1382.         (pointery == GOLDGADGET || pointery == SILVERGADGET || pointery == EMPTYGADGET || pointery == WOODGADGET || pointery == STONEGADGET || pointery == ONEGADGET || pointery == TWOGADGET || pointery == STARTGADGET))
  1383.         {    switch (pointery)
  1384.             {
  1385.             case GOLDGADGET:
  1386.                 setbrush(GOLD);
  1387.                 break;
  1388.             case SILVERGADGET:
  1389.                 setbrush(SILVER);
  1390.                 break;
  1391.             case EMPTYGADGET:
  1392.                 setbrush(EMPTY);
  1393.                 break;
  1394.             case WOODGADGET:
  1395.                 setbrush(WOOD);
  1396.                 break;
  1397.             case STONEGADGET:
  1398.                 setbrush(STONE);
  1399.                 break;
  1400.             case ONEGADGET:
  1401.                 setbrush(ONE);
  1402.                 break;
  1403.             case TWOGADGET:
  1404.                 setbrush(TWO);
  1405.                 break;
  1406.             case STARTGADGET:
  1407.                 setbrush(START);
  1408.                 break;
  1409.             default:
  1410.                 break;
  1411.     }    }    }
  1412.  
  1413.     if (stamp != NOSQUARE)
  1414.     {    if (stamp == START && board[level][x][y] != TELEPORT)
  1415.         {    if (x != startx[level] || y != starty[level])
  1416.             {    draw(startx[level], starty[level], EMPTY);
  1417.                 board[level][startx[level]][starty[level]] = EMPTY;
  1418.                 draw(x, y, START);
  1419.                 startx[level] = x;
  1420.                 starty[level] = y;
  1421.                 modified = TRUE;
  1422.                 clearthem = TRUE;
  1423.         }    }
  1424.         else if (x != startx[level] || y != starty[level])
  1425.         {    if (stamp == ONE || stamp == TWO)
  1426.             {    if (teleport[level][partner(stamp - ONE)].alive == FALSE || x != teleport[level][partner(stamp - ONE)].x || y != teleport[level][partner(stamp - ONE)].y)
  1427.                 {    if (teleport[level][stamp - ONE].alive == TRUE)
  1428.                     {    draw(teleport[level][stamp - ONE].x, teleport[level][stamp - ONE].y, EMPTY);
  1429.                         board[level][teleport[level][stamp - ONE].x][teleport[level][stamp - ONE].y] = EMPTY;
  1430.                     } else
  1431.                         teleport[level][stamp - ONE].alive = TRUE;
  1432.                     board[level][x][y] = TELEPORT;
  1433.                     draw(x, y, stamp);
  1434.                     teleport[level][stamp - ONE].x = x;
  1435.                     teleport[level][stamp - ONE].y = y;
  1436.                     modified = TRUE;
  1437.                     clearthem = TRUE;
  1438.             }    }
  1439.             else
  1440.             {    if (board[level][x][y] == TELEPORT)
  1441.                     if (teleport[level][0].alive == TRUE && x == teleport[level][0].x && y == teleport[level][0].y)
  1442.                         teleport[level][0].alive = FALSE;
  1443.                     else teleport[level][1].alive = FALSE;
  1444.                 draw(x, y, stamp);
  1445.                 board[level][x][y] = stamp;
  1446.                 modified = TRUE;
  1447.                 clearthem = TRUE;
  1448. }    }    }    }
  1449.  
  1450. // exit to title screen
  1451.  
  1452. if (timer)
  1453. {    AbortIO(TimerRqPtr);
  1454.     WaitIO(TimerRqPtr);
  1455.     timer = FALSE;
  1456. }
  1457. if (oldbrush != ANYTHING)
  1458.     brush = oldbrush;
  1459. setpointer(NORMAL);
  1460. clearstats();
  1461. if (clearthem)
  1462.     clearhiscores();
  1463. matchteleports();
  1464.  
  1465. ClearMenuStrip(MenuPtr);
  1466. menu = FALSE;
  1467. NewMenu[TOOLSSTART + 1 + IN_TS].nm_Flags  = CHECKIT | MENUTOGGLE | CHECKED | NM_ITEMDISABLED;
  1468. NewMenu[TOOLSSTART + 1 + IN_FE].nm_Flags  = CHECKIT | MENUTOGGLE;
  1469. NewMenu[LEVELSTART].nm_Flags = NM_MENUDISABLED;
  1470. if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
  1471. {    DisplayAlert(AT_Recovery, ALERTMENUCREATE, 24);
  1472.     cleanexit(EXIT_FAILURE);
  1473. }
  1474. if (!(LayoutMenus(MenuPtr, VisualInfoPtr, TAG_DONE)))
  1475. {    DisplayAlert(AT_Recovery, ALERTMENULAYOUT, 24);
  1476.     if (modified)
  1477.         savefields(EMERGENCYNAME);
  1478.     cleanexit(EXIT_FAILURE);
  1479. }
  1480. SetMenuStrip(MainWindowPtr, MenuPtr);
  1481. menu = TRUE;
  1482. }
  1483.  
  1484. void fileabout(void)
  1485. {    ABOOL                    done = FALSE;
  1486.     SBYTE                    line;
  1487.     UWORD                    code, qual;
  1488.     ULONG                    class;
  1489.     struct Window*            AboutWindowPtr;
  1490.     struct IntuiMessage*    MsgPtr;
  1491.     
  1492.     effect(FXFILEABOUT);
  1493.     if (!(AboutWindowPtr = (struct Window *) OpenWindowTags(NULL,
  1494.     WA_Left,            (SCREENXPIXEL / 2) - (ABOUTXPIXEL / 2),
  1495.     WA_Top,                (SCREENYPIXEL / 2) - (ABOUTYPIXEL / 2),
  1496.     WA_Width,            ABOUTXPIXEL,
  1497.     WA_Height,            ABOUTYPIXEL,
  1498.     WA_IDCMP,            IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  1499.     WA_Title,            "About Worm Wars",
  1500.     WA_Gadgets,            NULL,
  1501.     WA_CustomScreen,    ScreenPtr,
  1502.     WA_DragBar,            TRUE,
  1503.     WA_CloseGadget,        TRUE,
  1504.     WA_NoCareRefresh,    TRUE,
  1505.     WA_Activate,        TRUE,
  1506.     TAG_DONE)))
  1507.     {    say("Can't open About... window!", RED);
  1508.         anykey(TRUE);
  1509.     } else
  1510.     {    SetAPen(AboutWindowPtr->RPort, BLUE);
  1511.         RectFill(AboutWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 11, ABOUTYPIXEL - 6);
  1512.         SetAPen(AboutWindowPtr->RPort, ABOUTSHADOW);
  1513.         Move(AboutWindowPtr->RPort, 7, ABOUTYPIXEL - 5);
  1514.         Draw(AboutWindowPtr->RPort, 7, 12);
  1515.         Draw(AboutWindowPtr->RPort, ABOUTXPIXEL - 10, 12);
  1516.         SetAPen(AboutWindowPtr->RPort, ABOUTSHINE);
  1517.         Draw(AboutWindowPtr->RPort, ABOUTXPIXEL - 10, ABOUTYPIXEL - 5);
  1518.         Draw(AboutWindowPtr->RPort, 8, ABOUTYPIXEL - 5);
  1519.         SetAPen(AboutWindowPtr->RPort, BLACK);
  1520.         SetDrMd(AboutWindowPtr->RPort, JAM1);
  1521.         for (line = 0; line <= ABOUTLINES; line++)
  1522.         {    Move(AboutWindowPtr->RPort, about[line].x, about[line].y);
  1523.             Text(AboutWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
  1524.         }
  1525.         DrawBevelBox(AboutWindowPtr->RPort, 18, 21, 49, 23, GT_VisualInfo, VisualInfoPtr);
  1526.         DrawImage(AboutWindowPtr->RPort, &About, 20, 23);
  1527.         while (!done)
  1528.         {    while (MsgPtr = (struct IntuiMessage *) GetMsg(AboutWindowPtr->UserPort))
  1529.             {    class = MsgPtr->Class;
  1530.                 code  = MsgPtr->Code;
  1531.                 qual  = MsgPtr->Qualifier;
  1532.                 ReplyMsg(MsgPtr);
  1533.                 if (class == IDCMP_CLOSEWINDOW)
  1534.                     done = TRUE;
  1535.                 else if (class == IDCMP_RAWKEY)
  1536.                 {   if (code == SPACEBAR || code == RETURN || code == ENTER || code == HELP)
  1537.                         done = TRUE;
  1538.                     else if (code == ESCAPE)
  1539.                         if (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1540.                         {   if (verify())
  1541.                             {   CloseWindow(AboutWindowPtr);
  1542.                                 cleanexit(EXIT_SUCCESS);
  1543.                         }    }
  1544.                         else done = TRUE;
  1545.         }   }   }
  1546.         CloseWindow(AboutWindowPtr);
  1547.         clearkybd();
  1548. }    }
  1549.  
  1550. void fileopen(void)
  1551. {   TEXT temp1[81] = {"Opened "}, temp2[3], newpathname[255];
  1552.  
  1553.     strcpy(newpathname, pathname);
  1554.     if (AslRequestTags(ASLRqPtr, ASL_Hail, ASLOPENHAIL, ASL_FuncFlags, FILF_PATGAD, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
  1555.     {    strcpy(newpathname, ASLRqPtr->rf_Dir);
  1556.         AddPart(newpathname, ASLRqPtr->rf_File, 254);
  1557.         if (loadfields(newpathname))
  1558.         {   strcpy(pathname, newpathname);
  1559.             strcat(temp1, pathname);
  1560.             strcat(temp1, " (");
  1561.             stci_d(temp2, levels);
  1562.             strcat(temp1, temp2);
  1563.             strcat(temp1, " levels).");
  1564.             say(temp1, WHITE);
  1565.             if (a == FIELDEDIT)
  1566.                 renderboard();
  1567.             else hiscores();
  1568.         } else
  1569.         {   strcpy(temp1, "Couldn't open ");
  1570.             strcat(temp1, newpathname);
  1571.             strcat(temp1, "!");
  1572.             say(temp1, WHITE);
  1573.     }   }
  1574.     if (a == GAMEOVER)
  1575.         anykey(TRUE);
  1576. }
  1577.  
  1578. void filesaveas(ABOOL flag)
  1579. {    ABOOL    cont = TRUE;
  1580.     TEXT    newpathname[255], temp1[SAYLIMIT + 1], temp2[3];
  1581.  
  1582.     // flag is TRUE for 'save as...', FALSE for 'save'.
  1583.  
  1584.     strcpy(newpathname, pathname);
  1585.     if (flag)
  1586.         if (AslRequestTags(ASLRqPtr, ASL_Hail, ASLSAVEHAIL, ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
  1587.         {   strcpy(newpathname, ASLRqPtr->rf_Dir);
  1588.             AddPart(newpathname, ASLRqPtr->rf_File, 254);
  1589.         } else cont = FALSE;
  1590.     if (cont)
  1591.     {    strcpy(temp1, "Saving ");
  1592.         strcat(temp1, pathname);
  1593.         strcat(temp1, "...");
  1594.         say(temp1, WHITE);
  1595.         if (savefields(newpathname))
  1596.         {   strcpy(pathname, newpathname);
  1597.             strcpy(temp1, "Saved ");
  1598.             strcat(temp1, pathname);
  1599.             strcat(temp1, " (");
  1600.             stci_d(temp2, levels);
  1601.             strcat(temp1, temp2);
  1602.             strcat(temp1, " levels).");
  1603.         } else
  1604.         {   strcpy(temp1, "Couldn't save ");
  1605.             strcat(temp1, newpathname);
  1606.             strcat(temp1, "!");
  1607.         }
  1608.         say(temp1, WHITE);
  1609.         if (a == GAMEOVER)
  1610.             anykey(TRUE);
  1611. }   }
  1612.  
  1613. void freefx(void)
  1614. {    SBYTE i;
  1615.  
  1616.     stopfx(0L);
  1617.     if (!AudioClosed)
  1618.     {    CloseDevice((struct IORequest *) AudioRqPtr[0]);
  1619.         AudioClosed = TRUE;
  1620.     }
  1621.     for (i = 0; i <= 3; i++)
  1622.     {    if (AudioRqPtr[i])
  1623.         {    DeleteIORequest(AudioRqPtr[i]);
  1624.             AudioRqPtr[i] = NULL;
  1625.         }
  1626.         if (AudioPortPtr[i])
  1627.         {    DeleteMsgPort(AudioPortPtr[i]);
  1628.             AudioPortPtr[i] = NULL;
  1629.     }    }
  1630.     if (fbase)
  1631.     {    FreeMem(fbase, fsize);
  1632.         fbase = NULL;
  1633.     }
  1634.     if (FilePtr)
  1635.     {   Close((BPTR) FilePtr);
  1636.         FilePtr = NULL;
  1637. }    }
  1638.  
  1639. void gameinput(void)
  1640. {        ABOOL                    done;
  1641.         UWORD                    code, qual;
  1642.         ULONG                    class, Signal;
  1643. PERSIST    SBYTE                    joyy;
  1644.         struct IntuiMessage*    MsgPtr;
  1645.         ULONG                    SignalMask = 1L << MainWindowPtr->UserPort->mp_SigBit;
  1646.         SBYTE                    keyplayer, which;
  1647.  
  1648. for (which = 0; which <= NUMKEYS; which++)
  1649.     key[which].down = FALSE;
  1650.  
  1651. /* human control
  1652.  
  1653. keyboard */
  1654.  
  1655. while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  1656. {    class  = MsgPtr->Class;
  1657.     code   = MsgPtr->Code;
  1658.     qual   = MsgPtr->Qualifier;
  1659.     ReplyMsg(MsgPtr);
  1660.     if (class == IDCMP_RAWKEY && !(qual & IEQUALIFIER_REPEAT) && code < KEYUP)
  1661.     {    switch(code) {
  1662.         case M:
  1663.             toggle(M);
  1664.             break;
  1665.         case F:
  1666.             toggle(F);
  1667.             break;
  1668.         case P:
  1669.             clearkybd();
  1670.             say("Paused...press P to unpause", WHITE);
  1671.             GetSysTime(CurrentValPtr);
  1672.             done = FALSE;
  1673.             while (!done)
  1674.             {    Signal = Wait(SignalMask);
  1675.                 if (Signal & SignalMask)
  1676.                 {    if (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  1677.                     {    class = MsgPtr->Class;
  1678.                         code  = MsgPtr->Code;
  1679.                         qual  = MsgPtr->Qualifier;
  1680.                         ReplyMsg(MsgPtr);
  1681.                         if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
  1682.                         {    if (code == ESCAPE)
  1683.                             {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1684.                                 {    if (verify())
  1685.                                         cleanexit(EXIT_SUCCESS);
  1686.                                 } else
  1687.                                 {    a = GAMEOVER;
  1688.                                     worm[0].lives = 0;
  1689.                                     worm[1].lives = 0;
  1690.                                     worm[2].lives = 0;
  1691.                                     worm[3].lives = 0;
  1692.                                     done = TRUE;
  1693.                             }    }
  1694.                             else if (code == M)
  1695.                                 toggle(M);
  1696.                             else if (code == F)
  1697.                                 toggle(F);
  1698.                             else if (code == P)
  1699.                             {    say("Unpaused", WHITE);
  1700.                                 done = TRUE;
  1701.             }    }    }    }    }
  1702.             GetSysTime(PausedValPtr);
  1703.             SubTime(PausedValPtr, CurrentValPtr);
  1704.             AddTime(StartValPtr, PausedValPtr);
  1705.             break;
  1706.         case ESCAPE:
  1707.             if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1708.             {    if (verify())
  1709.                     cleanexit(EXIT_SUCCESS);
  1710.             } else
  1711.             {    a = GAMEOVER;
  1712.                 worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
  1713.             }
  1714.             break;
  1715.         default:
  1716.             for (which = 0; which <= NUMKEYS; which++)
  1717.                 if (code == key[which].scancode)
  1718.                     key[which].down = TRUE;
  1719.             break;
  1720.     }    }    
  1721.     else if (class == IDCMP_CLOSEWINDOW)
  1722.         cleanexit(EXIT_SUCCESS);
  1723.     else if (class == IDCMP_REFRESHWINDOW)
  1724.     {   GT_BeginRefresh(MainWindowPtr);
  1725.         GT_EndRefresh(MainWindowPtr, TRUE);
  1726. }   }
  1727. /* other IDCMP messages we receive but ignore are: IDCMP_ACTIVEWINDOW,
  1728. IDCMP_MOUSEBUTTONS, IDCMP_INTUITICKS. */
  1729.  
  1730. for (which = 0; which <= NUMKEYS; which++)
  1731. {    if (key[which].down)
  1732.     {    if (key[which].special == ONEHUMAN)
  1733.         {    if (worm[0].control == HUMAN && worm[1].control != HUMAN)
  1734.                 queue(0, key[which].deltax, key[which].deltay);
  1735.             else if (worm[0].control != HUMAN && worm[1].control == HUMAN)
  1736.                 queue(1, key[which].deltax, key[which].deltay);
  1737.         } else if (key[which].special == MOVE || key[which].special == AMMO)
  1738.         {   if (worm[key[which].player].control == HUMAN)
  1739.                 keyplayer = key[which].player;
  1740.             else if (key[which].player == 1 && worm[0].control == HUMAN && worm[1].control != HUMAN)
  1741.                 keyplayer = 0;
  1742.             else if (key[which].player == 0 && worm[1].control == HUMAN && worm[0].control != HUMAN)
  1743.                 keyplayer = 1;
  1744.             else keyplayer = -1;
  1745.             if (keyplayer != -1)
  1746.                 queue(keyplayer, key[which].deltax, key[which].deltay);
  1747.         } else if (worm[1].lives > 0) // assumes key[which].special == TRAINER
  1748.             train(key[which].scancode);
  1749. }    }
  1750.  
  1751. // joysticks
  1752.  
  1753. if (worm[2].control == HUMAN)
  1754.     while (GetMsg(JoyPortPtr))
  1755.     {    if (GameEvent.ie_position.ie_xy.ie_x != 0 || GameEvent.ie_position.ie_xy.ie_y != 0)
  1756.             if (ignorenextjoy && GameEvent.ie_position.ie_xy.ie_y == joyy)
  1757.                 ignorenextjoy = FALSE;
  1758.             else
  1759.             {    queue(2, GameEvent.ie_position.ie_xy.ie_x, GameEvent.ie_position.ie_xy.ie_y);
  1760.                 if (GameEvent.ie_position.ie_xy.ie_x == 1)
  1761.                 {    ignorenextjoy = TRUE;
  1762.                     joyy = GameEvent.ie_position.ie_xy.ie_y;
  1763.             }    }
  1764.         if (GameEvent.ie_Code == IECODE_LBUTTON)
  1765.             queue(2, 0, 0);
  1766.         sendreadrequest();
  1767.     }
  1768. }
  1769.  
  1770. void hiscores(void)
  1771. {    SBYTE                    which;
  1772.     TEXT                    tempstring[NAMELENGTH + 1];
  1773.  
  1774. /* render hiscores
  1775.  
  1776. darkdarkdarkdarkdarkdarkdarkdarkdark
  1777. a   a   a   a                      w
  1778. r   r   r   r                      h
  1779. k   k   k   k                      i
  1780. |   |   |   |                      t
  1781. whitewhitewhitewhitewhitewhitewhitee */
  1782.  
  1783. SetDrMd(MainWindowPtr->RPort, JAM1);
  1784. for (which = 0; which <= HISCORES; which++)
  1785. {    if (hiscore[which].player == -1)
  1786.         SetAPen(MainWindowPtr->RPort, LIGHTGREY);
  1787.     else SetAPen(MainWindowPtr->RPort, worm[hiscore[which].player].colour);
  1788.     RectFill(MainWindowPtr->RPort, 159, 105 + which * HISCOREDISTANCE, 481, 114 + which * HISCOREDISTANCE);
  1789.     if (hiscore[which].player == 0)
  1790.         SetAPen(MainWindowPtr->RPort, DARKGREEN);
  1791.     else if (hiscore[which].player == 1)
  1792.         SetAPen(MainWindowPtr->RPort, DARKRED);
  1793.     else if (hiscore[which].player == 2)
  1794.         SetAPen(MainWindowPtr->RPort, DARKBLUE);
  1795.     else if (hiscore[which].player == 3)
  1796.         SetAPen(MainWindowPtr->RPort, DARKYELLOW);
  1797.     else SetAPen(MainWindowPtr->RPort, DARKGREY);
  1798.     Move(MainWindowPtr->RPort, 158, 115 + which * HISCOREDISTANCE);
  1799.     Draw(MainWindowPtr->RPort, 158, 104 + which * HISCOREDISTANCE);
  1800.     Draw(MainWindowPtr->RPort, 482, 104 + which * HISCOREDISTANCE);
  1801.  
  1802.     if (hiscore[which].player != -1)
  1803.     {    // divider bars
  1804.     
  1805.         Move(MainWindowPtr->RPort, 182, 104 + which * HISCOREDISTANCE);
  1806.         Draw(MainWindowPtr->RPort, 182, 114 + which * HISCOREDISTANCE);
  1807.         Move(MainWindowPtr->RPort, 254, 104 + which * HISCOREDISTANCE);
  1808.         Draw(MainWindowPtr->RPort, 254, 114 + which * HISCOREDISTANCE);
  1809.         Move(MainWindowPtr->RPort, 290, 104 + which * HISCOREDISTANCE);
  1810.         Draw(MainWindowPtr->RPort, 290, 114 + which * HISCOREDISTANCE);
  1811.     }
  1812.     
  1813.     SetAPen(MainWindowPtr->RPort, WHITE);
  1814.     Move(MainWindowPtr->RPort, 159, 115 + which * HISCOREDISTANCE);
  1815.     Draw(MainWindowPtr->RPort, 482, 115 + which * HISCOREDISTANCE);
  1816.     Draw(MainWindowPtr->RPort, 482, 105 + which * HISCOREDISTANCE);
  1817.     SetAPen(MainWindowPtr->RPort, BLACK);
  1818.  
  1819.     if (hiscore[which].player != -1)
  1820.     {    stci_d(tempstring, which + 1);
  1821.         tempstring[1] = '.';
  1822.         Move(MainWindowPtr->RPort, 161, 112 + which * HISCOREDISTANCE);
  1823.         Text(MainWindowPtr->RPort, tempstring, 2);
  1824.         stci_d(tempstring, hiscore[which].score);
  1825.         align(tempstring, 7, ' ');
  1826.         Move(MainWindowPtr->RPort, 193, 112 + which * HISCOREDISTANCE);
  1827.         Text(MainWindowPtr->RPort, tempstring, 7);
  1828.         if (hiscore[which].level == -1)
  1829.             strcpy(tempstring, "All");
  1830.         else
  1831.         {    stci_d(tempstring, hiscore[which].level);
  1832.             align(tempstring, 3, ' ');
  1833.         }
  1834.         Move(MainWindowPtr->RPort, 261, 112 + which * HISCOREDISTANCE);
  1835.         Text(MainWindowPtr->RPort, tempstring, 3);
  1836.         Move(MainWindowPtr->RPort, 296, 112 + which * HISCOREDISTANCE);
  1837.         Text(MainWindowPtr->RPort, hiscore[which].name, strlen(hiscore[which].name));
  1838. }    }
  1839. SetDrMd(MainWindowPtr->RPort, JAM2);
  1840. }
  1841.  
  1842. void hiscorenames(void)
  1843. {
  1844. ULONG                    class;
  1845. ABOOL                    done;
  1846. SBYTE                    which;
  1847. struct IntuiMessage*    MsgPtr;
  1848.  
  1849. for (which = 0; which <= HISCORES; which++)
  1850.     if (hiscore[which].fresh)
  1851.     {    GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, FALSE, GTST_String, worm[hiscore[which].player].name, TAG_DONE);
  1852.         activate(which);
  1853.         done = FALSE;
  1854.         while (!done)
  1855.         {    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  1856.             {    class = MsgPtr->Class;
  1857.                 GT_ReplyIMsg(MsgPtr);
  1858.                 if (class == IDCMP_GADGETUP)
  1859.                     done = TRUE;
  1860.                 else if (class == IDCMP_MOUSEBUTTONS)
  1861.                     activate(which);
  1862.                 else if (class == IDCMP_REFRESHWINDOW)
  1863.                 {    GT_BeginRefresh(MainWindowPtr);
  1864.                     GT_EndRefresh(MainWindowPtr, TRUE);
  1865.         }    }    }
  1866.         GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  1867.         effect(FXHISCORE);
  1868.         strcpy(hiscore[which].name, ((struct StringInfo *) (StringGadgetPtr[which]->SpecialInfo))->Buffer);
  1869.         if (hiscore[which].name[0] >= 97 && hiscore[which].name[0] <= 123)
  1870.             hiscore[which].name[0] -= 32;
  1871.         strcpy(worm[hiscore[which].player].name, hiscore[which].name);
  1872.         hiscore[which].fresh = FALSE;
  1873.         hiscores();
  1874. }    }
  1875.  
  1876. void initsound(void)
  1877. {           SBYTE    i;
  1878.     PERSIST    UBYTE    chan[]    = {15};
  1879.             ABOOL    success    = TRUE;
  1880.  
  1881.     for (i = 0; i <= 3; i++)
  1882.     {   eversent[i] = FALSE;
  1883.         if (!(AudioPortPtr[i] = (struct MsgPort *) CreateMsgPort()))
  1884.         {   freefx();
  1885.             say("No port for effects!", RED);
  1886.             anykey(TRUE);
  1887.             mode = FALSE;
  1888.             blitmode(BLACK);
  1889.             draw(MUSICICON, ICONY, ANYTHING);
  1890.             blitmode(NORMAL);
  1891.             success = FALSE;
  1892.             break;
  1893.         } else if (!(AudioRqPtr[i] = (struct IOAudio *) CreateIORequest(AudioPortPtr[i], sizeof(struct IOAudio))))
  1894.         {   freefx();
  1895.             say("No I/O memory for effects!", RED);
  1896.             anykey(TRUE);
  1897.             mode = FALSE;
  1898.             blitmode(BLACK);
  1899.             draw(MUSICICON, ICONY, ANYTHING);
  1900.             blitmode(NORMAL);
  1901.             success = FALSE;
  1902.             break;
  1903.     }   }
  1904.     if (success)
  1905.     {   AudioRqPtr[0]->ioa_Request.io_Message.mn_ReplyPort      = AudioPortPtr[0];
  1906.         AudioRqPtr[0]->ioa_Request.io_Message.mn_Node.ln_Pri    = 127;
  1907.         AudioRqPtr[0]->ioa_AllocKey                             = 0;
  1908.         AudioRqPtr[0]->ioa_Data                                 = chan;
  1909.         AudioRqPtr[0]->ioa_Length                               = 1;
  1910.         if (AudioClosed = OpenDevice(AUDIONAME, 0L, (struct IORequest *) AudioRqPtr[0], 0L))
  1911.         {   freefx();
  1912.             say("Can't allocate all channels for effects!", RED);
  1913.             anykey(TRUE);
  1914.             mode = FALSE;
  1915.             blitmode(BLACK);
  1916.             draw(MUSICICON, ICONY, ANYTHING);
  1917.             blitmode(NORMAL);
  1918.         } else
  1919.         {   for (i = 1; i <= 3; i++)
  1920.                 CopyMem(AudioRqPtr[0], AudioRqPtr[i], sizeof(struct IOAudio));
  1921.             mode = FX;
  1922.             draw(MUSICICON, ICONY, FX);
  1923. }   }   }
  1924.  
  1925. /* WormWars 4.1 .fset/.FST format for fieldset contents and high
  1926. score table (Amiga and IBM-PC), as follows:
  1927.  
  1928. header
  1929.     TEXT[]                "FSET 4.1" (NULL-terminated)
  1930.     SBYTE                levels;
  1931. high score table
  1932.     for (slot = 0; slot <= HISCORES; slot++)
  1933.     {    SBYTE            hiscore[slot].player,
  1934.                         hiscore[slot].level;
  1935.         SLONG            hiscore[slot].score;
  1936.         TEXT[]            hiscore[slot].name (NULL-terminated)
  1937.     }
  1938. level data
  1939.     for (level = 0; level <= levels; level++)
  1940.     {    SBYTE            startx[level],
  1941.                         starty[level];
  1942.         ABOOL            teleport[level][0].alive;
  1943.         SBYTE            teleport[level][0].x,
  1944.                         teleport[level][0].y;
  1945.         ABOOL            teleport[level][1].alive;
  1946.         SBYTE            teleport[level][1].x,
  1947.                         teleport[level][1].y;
  1948.         for (x = 0; x <= FIELDX; x++)
  1949.             for (y = 0; y <= FIELDY; y++)
  1950.                 SBYTE    board[level][x][y];
  1951.     }
  1952. version string
  1953.     TEXT[]                "$VER: Worm Wars 4.1 (dd.mm.yy) $" (NULL-terminated) */
  1954.  
  1955. void resettime(void)
  1956. {    GetSysTime(StartValPtr);
  1957. }
  1958.  
  1959. void rundown(SBYTE player)
  1960. {    TEXT    tempstring[6];
  1961.     SBYTE    x, y;
  1962.     UWORD    counter = 0;
  1963.  
  1964.     SetAPen(MainWindowPtr->RPort, BLACK);
  1965.     RectFill(MainWindowPtr->RPort, STARTXPIXEL, STARTYPIXEL, ENDXPIXEL, ENDYPIXEL);
  1966.     SetAPen(MainWindowPtr->RPort, worm[player].colour);
  1967.  
  1968.     Image.ImageData = ImageData[TREASURE];
  1969.     DrawImage(MainWindowPtr->RPort, &Image, 201, 103);
  1970.     Move(MainWindowPtr->RPort, 218, 108);
  1971.     Text(MainWindowPtr->RPort, "Level Bonus:    ## x #00 =", 26);
  1972.     stci_d(tempstring, worm[player].multi);
  1973.     Move(MainWindowPtr->RPort, 218 + (FONTX * 21), 108);
  1974.     Text(MainWindowPtr->RPort, tempstring, 1);
  1975.     stci_d(tempstring, level - 1);
  1976.     align(tempstring, 2, ' ');
  1977.     Move(MainWindowPtr->RPort, 218 + (FONTX * 16), 108);
  1978.     Text(MainWindowPtr->RPort, tempstring, 2);
  1979.     stci_d(tempstring, (level - 1) * 100 * worm[player].multi);
  1980.     align(tempstring, 5, ' ');
  1981.     Move(MainWindowPtr->RPort, 218 + (FONTX * 27), 108);
  1982.     Text(MainWindowPtr->RPort, tempstring, 5);
  1983.  
  1984.     Image.ImageData = ImageData[CLOCK];
  1985.     DrawImage(MainWindowPtr->RPort, &Image, 201, 111);
  1986.     Move(MainWindowPtr->RPort, 226, 116);
  1987.     Text(MainWindowPtr->RPort,  "Time Bonus: ##:## x  #0 =", 25);
  1988.     stci_d(tempstring, worm[player].multi);
  1989.     Move(MainWindowPtr->RPort, 226 + (FONTX     * 21), 116);
  1990.     Text(MainWindowPtr->RPort, tempstring, 1);
  1991.     stci_d(tempstring, secondsleft / 60);
  1992.     align(tempstring, 2, ' ');
  1993.     Move(MainWindowPtr->RPort, 226 + (FONTX * 12), 116);
  1994.     Text(MainWindowPtr->RPort, tempstring, 2);
  1995.     stci_d(tempstring, secondsleft % 60);
  1996.     align(tempstring, 2, '0');
  1997.     Move(MainWindowPtr->RPort, 226 + (FONTX * 15), 116);
  1998.     Text(MainWindowPtr->RPort, tempstring, 2);
  1999.     stci_d(tempstring, secondsleft * 10 * worm[player].multi);
  2000.     align(tempstring, 5, ' ');
  2001.     Move(MainWindowPtr->RPort, 226 + (FONTX * 26), 116);
  2002.     Text(MainWindowPtr->RPort, tempstring, 5);
  2003.  
  2004.     Image.ImageData = ImageData[FIRSTTAIL + player];
  2005.     DrawImage(MainWindowPtr->RPort, &Image, 201, 119);
  2006.     Move(MainWindowPtr->RPort, 226, 124);
  2007.     Text(MainWindowPtr->RPort,  "Tail Bonus:  #### x   # =", 25);
  2008.     stci_d(tempstring, worm[player].multi);
  2009.     Move(MainWindowPtr->RPort, 226 + (FONTX * 22), 124);
  2010.     Text(MainWindowPtr->RPort, tempstring, 1);
  2011.     for (x = 0; x <= FIELDX; x++)
  2012.         for (y = 0; y <= FIELDY; y++)
  2013.             if (field[x][y] == FIRSTTAIL + player)
  2014.                 counter++;
  2015.     stci_d(tempstring, counter);
  2016.     align(tempstring, 4, ' ');
  2017.     Move(MainWindowPtr->RPort, 226 + (FONTX * 13), 124);
  2018.     Text(MainWindowPtr->RPort, tempstring, 4);
  2019.     stci_d(tempstring, counter * worm[player].multi);
  2020.     align(tempstring, 5, ' ');
  2021.     Move(MainWindowPtr->RPort, 226 + (FONTX * 26), 124);
  2022.     Text(MainWindowPtr->RPort, tempstring, 5);
  2023.  
  2024.     wormscore(player,    ((level - 1)    * 100) +
  2025.                          (secondsleft    * 10) +
  2026.                           counter);
  2027.  
  2028.     waitasec();
  2029.     anykey(FALSE);
  2030. }
  2031.  
  2032. void say(STRPTR sentence, COLOUR colour)
  2033. {    PERSIST SBYTE length = 0;
  2034.  
  2035.     SetAPen(MainWindowPtr->RPort, BLACK);
  2036.     RectFill(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - ((length * FONTX) / 2), 1, (SCREENXPIXEL / 2) + (length * FONTX / 2), FONTY + 1);
  2037.     SetAPen(MainWindowPtr->RPort, colour);
  2038.     length = (SBYTE) strlen(sentence);
  2039.     if (length > SAYLIMIT)
  2040.     {    *(sentence + SAYLIMIT - 1) = *(sentence + SAYLIMIT - 2) = *(sentence + SAYLIMIT - 3) = '.';
  2041.         length = SAYLIMIT;
  2042.     }
  2043.     Move(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - (length * FONTX / 2), FONTY);
  2044.     Text(MainWindowPtr->RPort, sentence, length);
  2045. }
  2046.     
  2047. void sendreadrequest(void)
  2048. {    JoyRqPtr->io_Command    = GPD_READEVENT;
  2049.     JoyRqPtr->io_Flags        = NULL;
  2050.     JoyRqPtr->io_Length        = sizeof(struct InputEvent);
  2051.     JoyRqPtr->io_Data        = (APTR) &GameEvent;
  2052.     SendIO(JoyRqPtr);
  2053. }
  2054.  
  2055. void setpointer(SBYTE pointer) {
  2056. switch (pointer) {
  2057. case GOLD:
  2058.     SetRGB4(&ScreenPtr->ViewPort, 17, 10,  8,  3);        // fill
  2059.     SetRGB4(&ScreenPtr->ViewPort, 18,  8,  4,  2);        // shadow
  2060.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12,  2);        // shine
  2061.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2062.     break;
  2063. case SILVER:
  2064.     SetRGB4(&ScreenPtr->ViewPort, 17, 10, 10, 10);        // fill
  2065.     SetRGB4(&ScreenPtr->ViewPort, 18,  6,  6,  6);        // shadow
  2066.     SetRGB4(&ScreenPtr->ViewPort, 19, 15, 15, 15);        // shine
  2067.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2068.     break;
  2069. case EMPTY:
  2070.     SetRGB4(&ScreenPtr->ViewPort, 17,  2,  2,  2);        // fill
  2071.     SetRGB4(&ScreenPtr->ViewPort, 18,  0,  0,  0);        // shadow
  2072.     SetRGB4(&ScreenPtr->ViewPort, 19,  6,  6,  6);        // shine
  2073.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2074.     break;
  2075. case WOOD:
  2076.     SetRGB4(&ScreenPtr->ViewPort, 17,  8,  4,  2);        // fill
  2077.     SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);        // shadow
  2078.     SetRGB4(&ScreenPtr->ViewPort, 19, 14,  8,  3);        // shine
  2079.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2080.     break;
  2081. case STONE:
  2082.     SetRGB4(&ScreenPtr->ViewPort, 17,  0,  0,  0);        // fill
  2083.     SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);        // shadow
  2084.     SetRGB4(&ScreenPtr->ViewPort, 19,  6,  6,  6);        // shine
  2085.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2086.     break;
  2087. default:
  2088.     SetRGB4(&ScreenPtr->ViewPort, 17, 14,  4,  4);        // fill
  2089.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3,  3);        // shadow
  2090.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 12);        // shine
  2091.     ClearPointer(MainWindowPtr);
  2092.     break; }
  2093. }
  2094.  
  2095. void stat(SBYTE player, SBYTE line)
  2096. {    ABOOL    print = TRUE;
  2097.     SBYTE    i, num[7];
  2098.  
  2099.     strcpy(num, "      ");    // 6 spaces
  2100.     switch (line) {
  2101.     case SCORELINE:
  2102.         do
  2103.         {    worm[player].oldscore += (LIFEMODULO - (worm[player].oldscore % LIFEMODULO));
  2104.             if (worm[player].score >= worm[player].oldscore)
  2105.             {    worm[player].lives++;
  2106.                 stat(player, LIVESLINE);
  2107.             }
  2108.         } while (worm[player].score > worm[player].oldscore);
  2109.         worm[player].oldscore = worm[player].score;
  2110.         if (worm[player].multi > 1)
  2111.             SetAPen(MainWindowPtr->RPort, WHITE);
  2112.         else
  2113.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2114.         if (worm[player].score > SCORELIMIT)
  2115.         {    strcpy(num, "!YEAH!");
  2116.             Move(MainWindowPtr->RPort, (FONTX * 2) + (worm[player].statx * (ENDXPIXEL + FONTX)), STARTYPIXEL + 6 + (line * FONTY) + (worm[player].staty * (ENDYPIXEL - ((LINES + 2) * FONTY))));
  2117.             Text(MainWindowPtr->RPort, num, 6);
  2118.             if (level <= levels)
  2119.             {    say("*!! ONE MILLION POINTS !!*", worm[player].colour);
  2120.                 celebrate();
  2121.             }
  2122.             print = FALSE;
  2123.             break;
  2124.         }
  2125.         else
  2126.         {    stcl_d(num, worm[player].score);
  2127.             for (i = 0; i <= 5; i++)
  2128.                 if (num[i] == 0)
  2129.                 {    num[i] = ' ';
  2130.                     break;
  2131.         }        }
  2132.         break;
  2133.     case LIVESLINE:
  2134.         if (worm[player].lives > STARTLIVES)
  2135.         {    SetAPen(MainWindowPtr->RPort, WHITE);
  2136.             if (worm[player].lives > LIVESLIMIT)
  2137.                 worm[player].lives = LIVESLIMIT;
  2138.         }
  2139.         else
  2140.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2141.         stci_d(num, worm[player].lives);
  2142.         for (i = 0; i <= 5; i++)
  2143.             if (num[i] == 0)
  2144.             {    num[i] = ' ';
  2145.                 break;
  2146.             }
  2147.         break;
  2148.     case BIASLINE:
  2149.         if (worm[player].bias > 0)
  2150.         {    if (worm[player].bias > BIASLIMIT)
  2151.                 worm[player].bias = BIASLIMIT;
  2152.             SetAPen(MainWindowPtr->RPort, WHITE);
  2153.         } else
  2154.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2155.         stci_d(num, worm[player].bias);
  2156.         for (i = 0; i <= 5; i++)
  2157.             if (num[i] == 0)
  2158.             {    num[i] = ' ';
  2159.                 break;
  2160.             }
  2161.         break;
  2162.     case AMMOLINE:
  2163.         if (worm[player].ammo > 0)
  2164.         {    if (worm[player].ammo > AMMOLIMIT)
  2165.                 worm[player].ammo = AMMOLIMIT;
  2166.             SetAPen(MainWindowPtr->RPort, WHITE);
  2167.         } else
  2168.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2169.         stci_d(num, worm[player].ammo);
  2170.         for (i = 0; i <= 5; i++)
  2171.             if (num[i] == 0)
  2172.             {    num[i] = ' ';
  2173.                 break;
  2174.             }
  2175.         break;
  2176.     case POWERLINE:
  2177.         switch(worm[player].power)
  2178.         {    case 0:
  2179.                 SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2180.                 strcpy(num, STATSINGLE);
  2181.                 break;
  2182.             case 2:
  2183.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2184.                 strcpy(num, STATTRIPLE);
  2185.                 break;
  2186.             case 4:
  2187.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2188.                 strcpy(num, STATQUINTUPLE);
  2189.                 break;
  2190.             case 6:
  2191.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2192.                 strcpy(num, STATSEPTUPLE);
  2193.                 break;
  2194.             default:
  2195.                 break;
  2196.         }
  2197.         break;
  2198.     case ARMOURLINE:
  2199.         if (worm[player].armour > MODELIMIT)
  2200.             worm[player].armour = MODELIMIT;
  2201.         if (worm[player].mode == ARMOUR)
  2202.             SetAPen(MainWindowPtr->RPort, WHITE);
  2203.         else
  2204.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2205.         stci_d(num, worm[player].armour);
  2206.         for (i = 0; i <= 5; i++)
  2207.             if (num[i] == 0)
  2208.             {    num[i] = ' ';
  2209.                 break;
  2210.             }
  2211.         break;
  2212.     case TONGUELINE:
  2213.         if (worm[player].tongue > MODELIMIT)
  2214.             worm[player].tongue = MODELIMIT;
  2215.         if (worm[player].mode == TONGUE)
  2216.             SetAPen(MainWindowPtr->RPort, WHITE);
  2217.         else
  2218.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2219.         stci_d(num, worm[player].tongue);
  2220.         for (i = 0; i <= 5; i++)
  2221.             if (num[i] == 0)
  2222.             {    num[i] = ' ';
  2223.                 break;
  2224.             }
  2225.         break;
  2226.     case SPEEDLINE:
  2227.         if (worm[player].nitro)
  2228.         {    SetAPen(MainWindowPtr->RPort, WHITE);
  2229.             if (worm[player].speed == VERYFAST)
  2230.                 strcpy(num, STATVERYFAST);
  2231.             else if (worm[player].speed == VERYSLOW)
  2232.                 strcpy(num, STATVERYSLOW);
  2233.         }
  2234.         else
  2235.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2236.         if (worm[player].speed == FAST)
  2237.             strcpy(num, STATFAST);
  2238.         else if (worm[player].speed == NORMAL)
  2239.             strcpy(num, STATNORMAL);
  2240.         else if (worm[player].speed == SLOW)
  2241.             strcpy(num, STATSLOW);
  2242.         break;
  2243.     default:
  2244.         print = FALSE;
  2245.         break;
  2246.     }
  2247.  
  2248.     if (print)
  2249.     {    Move(MainWindowPtr->RPort, (FONTX * 2) + (worm[player].statx * (ENDXPIXEL + FONTX)), STARTYPIXEL + 6 + (line * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2250.         Text(MainWindowPtr->RPort, num, 6);
  2251. }    }
  2252.  
  2253. void stopfx(ULONG receipt)
  2254. {    SBYTE i;
  2255.  
  2256.     if (mode == FX)
  2257.         for (i = 0; i <= 3; i++)
  2258.             if (eversent[i] && (!(CheckIO(AudioRqPtr[i]))) && (receipt == 0L || receipt == receipter[i]))
  2259.             {   AbortIO(AudioRqPtr[i]);
  2260.                 WaitIO(AudioRqPtr[i]);
  2261. }           }
  2262.  
  2263. void titlescreen(void)
  2264. {    SBYTE                    lisa = 0, object = 0, player, segment = 0;
  2265.     ULONG                    class, ormw = 0;
  2266.     UWORD                    code, qual;
  2267.     struct IntuiMessage*    MsgPtr;
  2268.     struct Gadget*            WhichGadgetPtr;
  2269.  
  2270.     effect(FXTITLESCREEN);
  2271.     blitmode(BLACK);
  2272.     draw(CLOCKICON, ICONY, ANYTHING);
  2273.     blitmode(NORMAL);
  2274.     Forbid();
  2275.     MainWindowPtr->Flags = WFLG_BORDERLESS | WFLG_ACTIVATE;
  2276.     Permit();
  2277.     SetAPen(MainWindowPtr->RPort, BLACK);
  2278.     RectFill(MainWindowPtr->RPort, STARTXPIXEL, STARTYPIXEL, ENDXPIXEL, ENDYPIXEL);
  2279.  
  2280.     SetMenuStrip(MainWindowPtr, MenuPtr);
  2281.     for (player = 0; player <= 3; player++)
  2282.         GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  2283.  
  2284.     clearkybd();
  2285.     clearjoystick();
  2286.     hiscores();
  2287.     hiscorenames();
  2288.     
  2289.     do
  2290.     {    TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  2291.         TimerRqPtr->tr_time.tv_secs        = 0;
  2292.         TimerRqPtr->tr_time.tv_micro    = ANIMDELAY;
  2293.         SendIO(TimerRqPtr);
  2294.  
  2295.         /* W     W  OOOO  RRRRR  MM   MM
  2296.            W     W O    O R    R M M M M
  2297.            W  W  W O    O RRRRR  M  M  M
  2298.            W W W W O    O R R    M     M
  2299.            WW   WW  OOOO  R  RRR M     M */
  2300.  
  2301.         if (segment == 0)
  2302.         {    worm[0].x = FIELDX / 2 - 14;
  2303.             worm[0].y = 1;
  2304.             worm[1].x = FIELDX / 2 -  5;
  2305.             worm[1].y = 1;
  2306.             worm[2].x = FIELDX / 2 +  1;
  2307.             worm[2].y = 5;
  2308.             worm[3].x = FIELDX / 2 +  8;
  2309.             worm[3].y = 5;
  2310.         }
  2311.         for (player = 0; player <= 3; player++)
  2312.             if (anim[player][segment].x != SENTINEL)
  2313.             {    draw(worm[player].x, worm[player].y, FIRSTTAIL + ((player + ormw) % 4));
  2314.                 worm[player].x += anim[player][segment].x;
  2315.                 worm[player].y += anim[player][segment].y;
  2316.                 draw(worm[player].x, worm[player].y, eachworm[(player + ormw) % 4][0][anim[player][segment].x + 1 + (anim[player][segment].y + 1) * 3]);
  2317.             }
  2318.         if (++segment > SEGMENTS)
  2319.         {    segment = 0;
  2320.             if (++ormw == 1)
  2321.             {    effect(FXSTAMPED);
  2322.                 DrawImage(MainWindowPtr->RPort, &Logo, 203, 50);
  2323.             }
  2324.             if (++object > LASTOBJECT)
  2325.                 object = 0;
  2326.             say(objectdesc[object], WHITE);
  2327.             Image.ImageData = ImageData[object];
  2328.             DrawImage(MainWindowPtr->RPort, &Image, FIRSTDESCX, DESCY);
  2329.             DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
  2330.         }
  2331.  
  2332.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  2333.         {    WhichGadgetPtr = (struct Gadget *) MsgPtr->IAddress;
  2334.             class = MsgPtr->Class;
  2335.             code  = MsgPtr->Code;
  2336.             qual  = MsgPtr->Qualifier;
  2337.             GT_ReplyIMsg(MsgPtr);
  2338.             switch (class) {
  2339.             case IDCMP_RAWKEY:
  2340.                 if (!(qual & IEQUALIFIER_REPEAT))
  2341.                     switch (code) {
  2342.                     case F:
  2343.                         toggle(F);
  2344.                         break;
  2345.                     case M:
  2346.                         toggle(M);
  2347.                         break;
  2348.                     case SPACEBAR:
  2349.                         effect(FXCLICK);
  2350.                         a = FIELDEDIT;
  2351.                         break;
  2352.                     case F1:
  2353.                     case ALPHAONE:
  2354.                     case NUMERICONE:
  2355.                         effect(FXCLICK);
  2356.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2357.                         {    if (--worm[0].control < 0)
  2358.                                 worm[0].control = 2;
  2359.                         } else
  2360.                         {    if (++worm[0].control > 2)
  2361.                                 worm[0].control = 0;
  2362.                         }
  2363.                         GT_SetGadgetAttrs(CycleGadgetPtr[0], MainWindowPtr, NULL, GTCY_Active, worm[0].control, TAG_DONE);
  2364.                         break;
  2365.                     case F2:
  2366.                     case ALPHATWO:
  2367.                     case NUMERICTWO:
  2368.                         effect(FXCLICK);
  2369.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2370.                         {    if (--worm[1].control < 0)
  2371.                                 worm[1].control = 2;
  2372.                         } else
  2373.                         {    if (++worm[1].control > 2)
  2374.                                 worm[1].control = 0;
  2375.                         }
  2376.                         GT_SetGadgetAttrs(CycleGadgetPtr[1], MainWindowPtr, NULL, GTCY_Active, worm[1].control, TAG_DONE);
  2377.                         break;
  2378.                     case F3:
  2379.                     case ALPHATHREE:
  2380.                     case NUMERICTHREE:
  2381.                         effect(FXCLICK);
  2382.                         if (joy)
  2383.                         {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2384.                             {    if (--worm[2].control < 0)
  2385.                                     worm[2].control = 2;
  2386.                             } else
  2387.                             {    if (++worm[2].control > 2)
  2388.                                     worm[2].control = 0;
  2389.                         }    }
  2390.                         else if (worm[2].control == NONE)
  2391.                             worm[2].control = AMIGA;
  2392.                         else
  2393.                             worm[2].control = NONE;
  2394.                         GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
  2395.                         break;
  2396.                     case F4:
  2397.                     case ALPHAFOUR:
  2398.                     case NUMERICFOUR:
  2399.                         effect(FXCLICK);
  2400.                         if (worm[3].control == NONE)
  2401.                             worm[3].control = AMIGA;
  2402.                         else
  2403.                             worm[3].control = NONE;
  2404.                         GT_SetGadgetAttrs(CycleGadgetPtr[3], MainWindowPtr, NULL, GTCY_Active, worm[3].control, TAG_DONE);
  2405.                         break;
  2406.                     case RETURN:
  2407.                     case ENTER:
  2408.                         a = PLAYGAME;
  2409.                         break;
  2410.                     case ESCAPE:
  2411.                         if (verify())
  2412.                             cleanexit(EXIT_SUCCESS);
  2413.                         break;
  2414.                     case HELP:
  2415.                         fileabout();
  2416.                         break;
  2417.                     case INTERNATIONALONE:
  2418.                         if (lisa == 2)
  2419.                         {    say(FIRSTLISA, RED);
  2420.                             anykey(FALSE);
  2421.                             lisa = 0;
  2422.                         } else
  2423.                             lisa = 1;
  2424.                         break;
  2425.                     case INTERNATIONALTWO:
  2426.                         if (lisa == 1)
  2427.                         {    say(SECONDLISA, BLUE);
  2428.                             anykey(FALSE);
  2429.                             lisa = 0;
  2430.                         } else
  2431.                             lisa = 2;
  2432.                         break;
  2433.                     default:
  2434.                         break;
  2435.                     }
  2436.                 break;
  2437.             case IDCMP_MENUPICK:
  2438.                 if (code != MENUNULL)
  2439.                 {    switch (MENUNUM(code))
  2440.                     {
  2441.                     case MN_PROJECT:
  2442.                         switch (ITEMNUM(code))
  2443.                         {
  2444.                         case IN_NEW:
  2445.                             effect(FXFILENEW);
  2446.                             newfields();
  2447.                             say("New done.", WHITE);
  2448.                             anykey(TRUE);
  2449.                             say(objectdesc[object], WHITE);
  2450.                             break;
  2451.                         case IN_OPEN:
  2452.                             effect(FXFILEOPEN);
  2453.                             fileopen();
  2454.                             say(objectdesc[object], WHITE);
  2455.                             break;
  2456.                         case IN_SAVE:
  2457.                             effect(FXFILESAVE);
  2458.                             filesaveas(FALSE);
  2459.                             say(objectdesc[object], WHITE);
  2460.                             break;
  2461.                         case IN_SAVEAS:
  2462.                             effect(FXFILESAVEAS);
  2463.                             filesaveas(TRUE);
  2464.                             say(objectdesc[object], WHITE);
  2465.                             break;
  2466.                         case IN_ABOUT:
  2467.                             fileabout();
  2468.                             break;
  2469.                         case IN_QUIT:
  2470.                             if (verify())
  2471.                                 cleanexit(EXIT_SUCCESS);
  2472.                             break;
  2473.                         default:
  2474.                             break;
  2475.                         }
  2476.                         break;
  2477.                     case MN_TOOLS:
  2478.                         a = FIELDEDIT;
  2479.                         break;
  2480.                     default:
  2481.                         break;
  2482.                 }    }
  2483.                 break;
  2484.             case IDCMP_MOUSEBUTTONS:
  2485.                 if (ignore)
  2486.                 {    if (code == SELECTUP)
  2487.                         ignore = FALSE;
  2488.                 } else a = PLAYGAME;
  2489.                 break;
  2490.             case IDCMP_REFRESHWINDOW:
  2491.                 GT_BeginRefresh(MainWindowPtr);
  2492.                 GT_EndRefresh(MainWindowPtr, TRUE);
  2493.                 break;
  2494.             case IDCMP_GADGETUP:
  2495.                 for (player = 0; player <= 3; player++)
  2496.                     if (WhichGadgetPtr == CycleGadgetPtr[player])
  2497.                     {    if (code == HUMAN && player == 2 && (!joy))
  2498.                         {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2499.                                 worm[2].control = NONE;
  2500.                             else
  2501.                                 worm[2].control = AMIGA;
  2502.                             GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
  2503.                         } else
  2504.                             worm[player].control = code;
  2505.                         break;
  2506.                     }
  2507.                 break;
  2508.             case IDCMP_ACTIVEWINDOW:
  2509.                 ignore = TRUE;
  2510.                 break;
  2511.             case IDCMP_CLOSEWINDOW:
  2512.                 cleanexit(EXIT_SUCCESS);
  2513.                 break;
  2514.             default:
  2515.                 // IDCMP_MENUVERIFY, IDCMP_INTUITICKS
  2516.                 break;
  2517.         }    }
  2518.         if (joy && GetMsg(JoyPortPtr))
  2519.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  2520.                 a = PLAYGAME;
  2521.             sendreadrequest();
  2522.         }
  2523.         if (a == PLAYGAME)
  2524.         {    if (worm[0].control == NONE && worm[1].control == NONE && worm[2].control == NONE && worm[3].control == NONE)
  2525.             {    say("No worms active!", WHITE);
  2526.                 anykey(TRUE);
  2527.                 a = GAMEOVER;
  2528.         }    }
  2529.         if (CheckIO(TimerRqPtr))
  2530.             draw(CLOCKICON,ICONY, CLOCK);
  2531.         else
  2532.         {    blitmode(BLACK);
  2533.             draw(CLOCKICON, ICONY, ANYTHING);
  2534.             blitmode(NORMAL);
  2535.         }
  2536.         WaitIO(TimerRqPtr);
  2537.     } while (a == GAMEOVER);
  2538.  
  2539.     for (player = 0; player <= 3; player++)
  2540.         GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2541.     Image.ImageData = ImageData[object];
  2542.     blitmode(BLACK);
  2543.     DrawImage(MainWindowPtr->RPort, &Image, FIRSTDESCX, DESCY);
  2544.     DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
  2545.     blitmode(NORMAL);
  2546.     if (a == FIELDEDIT)
  2547.         fieldedit();
  2548.     else
  2549.     {    newgame();
  2550.         for (player = 0; player <= 3; player++)
  2551.         {    if (worm[player].control != NONE)
  2552.             {    Image.ImageData = ImageData[BONUS];
  2553.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 +  (SCORELINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2554.                 Image.ImageData = ImageData[LIFE];
  2555.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 +  (LIVESLINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2556.                 Image.ImageData = ImageData[BIAS];
  2557.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 +   (BIASLINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2558.                 Image.ImageData = ImageData[NITRO];
  2559.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 +  (SPEEDLINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2560.                 Image.ImageData = ImageData[AMMO];
  2561.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 +   (AMMOLINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2562.                 Image.ImageData = ImageData[POWER];
  2563.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 +  (POWERLINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2564.                 Image.ImageData = ImageData[ARMOUR];
  2565.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 + (ARMOURLINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2566.                 Image.ImageData = ImageData[TONGUE];
  2567.                 DrawImage(MainWindowPtr->RPort, &Image, worm[player].statx * (ENDXPIXEL + FONTX), STARTYPIXEL + 1 + (TONGUELINE * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - ((LINES + 2) * FONTY))));
  2568.             } else worm[player].lives = 0;
  2569.         }
  2570.         clearkybd();
  2571.         Forbid();
  2572.         MainWindowPtr->Flags = WFLG_BORDERLESS | WFLG_ACTIVATE | WFLG_RMBTRAP;
  2573.         Permit();
  2574. }    }
  2575.  
  2576. void toggle(SBYTE key)
  2577. {    PERSIST ABOOL songstarted = FALSE;
  2578.  
  2579.     if (key == F)
  2580.     {    if (mode == FX)                    // F in FX mode: no sound
  2581.         {    freefx();
  2582.             mode = FALSE;
  2583.             blitmode(BLACK);
  2584.             draw(MUSICICON, ICONY, ANYTHING);
  2585.             blitmode(NORMAL);
  2586.         } else if (fxable)                // F otherwise: change to FX mode
  2587.         {    if (mode == MUSIC)
  2588.             {    StopPlayer();
  2589.                 FreePlayer();
  2590.             }
  2591.             initsound();
  2592.             mode = FX;
  2593.             effect(FXFX);
  2594.     }    }
  2595.     else                                // assumes key is M
  2596.     {    if (mode == MUSIC)                // M in MUSIC mode: no sound
  2597.         {    StopPlayer();
  2598.             FreePlayer();
  2599.             mode = FALSE;
  2600.             blitmode(BLACK);
  2601.             draw(MUSICICON, ICONY, ANYTHING);
  2602.             blitmode(NORMAL);
  2603.         } else if (musicable)            // M otherwise: change to music mode
  2604.         {    if (mode == FX)
  2605.                 freefx();
  2606.             if (GetPlayer(0))
  2607.             {    say("No channels for music!", RED);
  2608.                 anykey(TRUE);
  2609.                 mode = FALSE;
  2610.                 blitmode(BLACK);
  2611.                 draw(MUSICICON, ICONY, ANYTHING);
  2612.                 blitmode(NORMAL);        
  2613.             } else
  2614.             {    if (songstarted)
  2615.                     ContModule(SongPtr);
  2616.                 else
  2617.                 {    PlayModule(SongPtr);
  2618.                     songstarted = TRUE;
  2619.                 }
  2620.                 mode = MUSIC;
  2621.                 draw(MUSICICON, ICONY, MUSIC);
  2622. }    }    }    }
  2623.  
  2624. void underline(SBYTE square)
  2625. {    /* Removes old underline, draws new underline.
  2626.     
  2627.     square: which square-type to underline, or -1 for clear only.
  2628.     Squares which do not correspond to any pseudo-gadgets
  2629.     (eg. objects) are converted to -1s. */
  2630.  
  2631. PERSIST    SWORD oldy = -1;
  2632.         SWORD y;
  2633.  
  2634.     switch(square)
  2635.     {
  2636.     case GOLD:
  2637.         y = UNDERLINEOFFSET;
  2638.         break;
  2639.     case SILVER:
  2640.         y = UNDERLINEOFFSET + (SQUAREY *  3);
  2641.         break;
  2642.     case EMPTY:
  2643.         y = UNDERLINEOFFSET + (SQUAREY *  6);
  2644.         break;
  2645.     case WOOD:
  2646.         y = UNDERLINEOFFSET + (SQUAREY *  9);
  2647.         break;
  2648.     case STONE:
  2649.         y = UNDERLINEOFFSET + (SQUAREY * 12);
  2650.         break;
  2651.     case ONE:
  2652.         y = UNDERLINEOFFSET + (SQUAREY * 15);
  2653.         break;
  2654.     case TWO:
  2655.         y = UNDERLINEOFFSET + (SQUAREY * 18);
  2656.         break;
  2657.     case START:
  2658.         y = UNDERLINEOFFSET + (SQUAREY * 21);
  2659.         break;
  2660.     default:
  2661.         square = -1;
  2662.         break;
  2663.     }
  2664.  
  2665.     if (oldy != -1)
  2666.     {    SetAPen(MainWindowPtr->RPort, BLACK);
  2667.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy);
  2668.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy + SQUAREY + 3);
  2669.     }
  2670.     if (square != -1)
  2671.     {    SetAPen(MainWindowPtr->RPort, WHITE);
  2672.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y);
  2673.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y + SQUAREY + 3);
  2674.         oldy = y;
  2675. }    }
  2676.  
  2677. ABOOL verify(void)
  2678. {    if (modified && (EasyRequest(MainWindowPtr, &EasyStruct, NULL) == 0))
  2679.         return(FALSE);
  2680.     else
  2681.         return(TRUE);
  2682. }
  2683.  
  2684. void waitasec(void)
  2685. {   Delay(50);
  2686. }
  2687.  
  2688. void systemsetup(void)
  2689. {    worm[0].control    = NONE;
  2690.     worm[1].control    = HUMAN;
  2691.     worm[2].control    = NONE;
  2692.     worm[3].control = AMIGA;
  2693. }
  2694.  
  2695. ABOOL ZOpen(STRPTR fieldname, ABOOL write)
  2696. {    if (FilePtr = (struct FileHandle *) Open(fieldname, MODE_READWRITE))
  2697.         return TRUE;
  2698.     else return FALSE;
  2699. }
  2700. ABOOL ZRead(STRPTR IOBuffer, ULONG length)
  2701. {    if (Read((BPTR) FilePtr, IOBuffer, length) == length)
  2702.         return TRUE;
  2703.     else return FALSE;
  2704. }
  2705. ABOOL ZWrite(STRPTR IOBuffer, ULONG length)
  2706. {    if (Write((BPTR) FilePtr, IOBuffer, length) == length)
  2707.         return TRUE;
  2708.     else return FALSE;
  2709. }
  2710. ABOOL ZClose(void)
  2711. {    if (Close((BPTR) FilePtr))
  2712.     {    FilePtr = NULL;
  2713.         return TRUE;
  2714.     } else return FALSE;
  2715. }
  2716.  
  2717. void timeronoff(ABOOL state)
  2718. {    ;
  2719. }
  2720.  
  2721. // Must have blank line at EOF.
  2722.